有没有办法只改变列表的第一个元素而不做像哈克那样的事情:
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(_))
有类似的吗?
答案 0 :(得分:15)
您可以尝试使用模式匹配
val l2 = l1 match{
case Nil => Nil
case x::xs => change(x)::xs
}
这样,如果head
实际返回元素
答案 1 :(得分: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)
答案 2 :(得分:5)
使用部分镜头(described in this paper),您可以编写如下内容:
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.但我不确定。
答案 3 :(得分: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)
答案 4 :(得分: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)