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

时间:2012-05-14 17:30:51

标签: list scala map

有没有办法只改变列表的第一个元素而不做像哈克那样的事情:

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(_))

有类似的吗?

5 个答案:

答案 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)