2012-05-14 76 views
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(_)) 

有类似的东西?

+3

是'val l2 = change(l1.head):: l1.tail'真的是“super hacky”吗? – stew

+0

也许不是,虽然每个人都提出了很多替代品,看起来更好。我认为罗伯特的模式匹配方法是最简单的。 – pr1001

回答

15

你可以尝试使用模式匹配

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

这样,你不必担心,如果head实际上返回元素

+0

模式匹配岩石!好一个。 –

8

您是通过在每一个机会引入变量让你的生活更加困难。不要这样做!

双方你列出的选项还算干净,如果你不采取临时变量:

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) 
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) 
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.我不确定。

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)