仅转换Scala列表的第一个元素

pr1*_*001 5 scala list map

有没有办法只转换列表的第一个元素而不做像超级hacky这样的事情:

val head = l1.head
val tail = l1.tail
val l2   = change(head) :: tail
Run Code Online (Sandbox Code Playgroud)

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

val head = l1.head
val l2   = l.update(0, change(head))
Run Code Online (Sandbox Code Playgroud)

我喜欢这样的东西:

val l2   = l1.updateHead(change(_))
Run Code Online (Sandbox Code Playgroud)

有什么相似的吗?

Rob*_*ert 16

你可以尝试使用模式匹配

val l2 = l1 match{
    case Nil   => Nil
    case x::xs => change(x)::xs
}
Run Code Online (Sandbox Code Playgroud)

这样你就不必担心head实际上是否会返回一个元素


Rex*_*err 9

通过在每个机会引入变量,您正在努力工作.不要这样做!

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

val l2 = change(l.head) :: l.tail
val l2 = l.update(0, change(l.head))
Run Code Online (Sandbox Code Playgroud)

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

val l2 = l.take(1).map(change) ::: l.drop(1)
Run Code Online (Sandbox Code Playgroud)

是.

您也可以使用自己的方法自由地丰富列表,但是:

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)
Run Code Online (Sandbox Code Playgroud)

(编辑 - 更改以避免空列表出错).现在你可以

val l2 = l.rehead(change)
Run Code Online (Sandbox Code Playgroud)


mis*_*tor 5

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

listHeadLens.set(list, newValue)
Run Code Online (Sandbox Code Playgroud)

其中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))
  }
}
Run Code Online (Sandbox Code Playgroud)

我认为部分镜头会进入Scalaz 7.但我不确定.