我想在Scala中创建通用(不变)方法,该方法将元素从源列表复制到目标列表。在Java中, java.util.Collections 中有 copy 方法(请参阅http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html#copy%28java.util.List,%20java.util.List%29)。我知道在Scala List中是不可变对象所以我想创建并返回新列表。
我写了以下代码:
def copy[T](dest:List[T], src:List[T]):List[T] = {
if(dest.length<src.length) throw new Exception("IndexOutOfBoundsException")
else if(src==Nil) dest
else {
var ret = dest
ret = dest.updated(0, src.first)
var i=1
val f:(T=>Unit) = a => {
if(i<src.length) ret=ret.updated(i, src(i))
i+=1
()
}
dest.foreach(f)
ret
}
}
但我认为它写得更好。你能帮我写出更好的代码吗?提前谢谢。
已编辑:也许我不清楚我想做什么。我有两个列表(scala.collection.immutable.List),例如 src (length = x)和 dest (length = y&gt; = x)。我想用 src 列表中的元素替换 dest 列表的第一个 x 元素。
答案 0 :(得分:8)
你的意思是scala.collection.immutable.List
?这是不可改变的。无需复制它们。不可变意味着什么都不能改变它,所以你可以在不同的线程中使用它。
在scala中创建集合的一般方法是构建器。您可以从CanBuildFrom
对象中获取一个。或者,您可以从genericBuilder
集合实例方法中获取它。
scala> val list = List(1, 2, 3)
list: List[Int] = List(1, 2, 3)
scala> val b = list.genericBuilder[Int]
b: scala.collection.mutable.Builder[Int,List[Int]] = ListBuffer()
scala> list.foreach{ b += _ }
scala> val result = b.result // this code is useless. `val result = list` is enough
result: List[Int] = List(1, 2, 3)
如果你想根据现有的集合创建不同类型的新集合,你可以像这样使用collection.breakOut
methid:
scala> val list = List('a', 'b', 'c')
list: List[Char] = List(a, b, c)
scala> val result: String = list.map{identity}(collection.breakOut)
result: String = abc
<强> UPD 强>
require(src.length <= dest.length, "IndexOutOfBoundsException")
src ++ dest.drop(src.length)
答案 1 :(得分:3)
你的想法太过于程序化,说出你不想怎么做......
怎么样:
val src = List(1,2,3)
val dest = src map {x => x}
如果你真的想要它的功能
def copy[T](src: List[T]): List[T] = src map {x => x}
响应OP的更新:(其他人也提出)
def copy[T](src: List[T], dest: List[T]): List[T] = src ++ dest.drop(src.length)
答案 2 :(得分:3)
如果您想获得更新列表,可以使用列表中的地图。 Map通过将函数应用于列表中的每个元素并返回更新列表来工作。
http://www.brunton-spall.co.uk/post/2011/12/02/map-map-and-flatmap-in-scala/
答案 3 :(得分:2)
您可以使用:
if(dest.length <= src.length) dest ::: src.drop(dest.length)
else dest.dropRight(dest.length - src.length) //or throw exception...
答案 4 :(得分:1)
也许你想要像
这样的东西 def copy[T](dest: Seq[T], src: Seq[T]): Seq[T] = {
require(dest.length >= src.length)
src ++ (dest drop src.length)
}
我推广到Seq
,但它适用于List
s,当然
require
方法如果在运行时未满足,则抛出IllegalArgumentException
然后你只需要将目的地列表的最后一个(y-x
)元素附加到源列表(其中x = src.length; y = dest.length)
您可以通过从x
中删除 dest
元素并将追加其余元素添加到src
来完成此操作。
这是你从REPL获得的
scala> val src = List(1, 2, 3, 4)
src: List[Int] = List(1, 2, 3, 4)
scala> val dst = List(10, 20)
dst: List[Int] = List(10, 20)
scala> val dst2 = List(10, 20, 30, 40, 50, 60)
dst2: List[Int] = List(10, 20, 30, 40, 50, 60)
scala> copy(dst, src)
java.lang.IllegalArgumentException: requirement failed
at scala.Predef$.require(Predef.scala:221)
at .copy(<console>:8)
at .<init>(<console>:11)
at .<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
<...>
scala> copy(dst2, src)
res1: Seq[Int] = List(1, 2, 3, 4, 50, 60)