5

有没有办法只转换列表的第一个元素而不做一些超级黑客的事情,比如:

val head = l1.head
val tail = l1.tail
val l2   = change(head) :: tail

updated()看起来它可以工作,但并没有太大的改进:

val head = l1.head
val l2   = l.update(0, change(head))

我喜欢这样的东西:

val l2   = l1.updateHead(change(_))

有这样的吗?

4

5 回答 5

16

你可以尝试使用模式匹配

val l2 = l1 match{
    case Nil   => Nil
    case x::xs => change(x)::xs
}

这样你就不用担心是否head真的返回一个元素

于 2012-05-14T17:37:46.913 回答
9

通过在每一个机会中引入变量,你让你的生活变得更加艰难。不要这样做!

如果您不引入临时变量,您列出的两个选项都相当干净:

val l2 = change(l.head) :: l.tail
val l2 = l.update(0, change(l.head))

在空列表上两者都不是完全安全的,但是

val l2 = l.take(1).map(change) ::: l.drop(1)

是。

您也可以随时使用自己的方法来丰富列表,但是:

class ReheadableList[A](xs: List[A]) {
  def rehead[B >: A](f: A => B) = xs.take(1).map(f) ::: xs.drop(1)
}
implicit def lists_can_be_reheaded[A](xs: List[A]) = new ReheadableList(xs)

(编辑——更改以避免空列表错误)。现在你可以

val l2 = l.rehead(change)
于 2012-05-14T17:44:35.647 回答
5

使用部分镜头(在本文中描述),您可以编写如下内容:

listHeadLens.set(list, newValue)

其中listHeadLens定义为:

def listHeadLens[A] = new PartialLens[List[A], A] {
  def apply: List[A] => Option[CoState[A, List[A]]] = {
    case Nil => None
    case x :: xs => Some(CoState(x, _ :: xs))
  }
}

我认为部分镜头将进入 Scalaz 7。不过我不确定。

于 2012-05-14T17:55:14.777 回答
3

可能有很多方法可以做到这一点。下面是一个显示一个版本的 Scala REPL 会话

scala> val change = (x: Int) => x*2
change: Int => Int = <function1>

scala> val l = List(1,2,3)
l: List[Int] = List(1, 2, 3)

scala> l.headOption.map( x => change(x) :: l.drop(1) ).getOrElse(Nil)
res3: List[Int] = List(2, 2, 3)
于 2012-05-14T17:53:03.663 回答
1

你可以这样做。

val list = List("1","2","3")
def change(str : String ) = Some("x")

val nlist = (list.headOption.flatMap(change(_)).toList ::: list.tail)

在控制台中。

scala> val list = List("1","2","3")
list: List[java.lang.String] = List(1, 2, 3)

scala> def change(str : String ) = Some("x")
change: (str: String)Some[java.lang.String]

scala> val nlist = (list.headOption.flatMap(change(_)).toList ::: list.tail)          
nlist: List[java.lang.String] = List(x, 2, 3)
于 2012-05-14T18:15:37.003 回答