繁体   English   中英

在Scala中将元素从一个列表复制到另一个列表

[英]Copy elements from one list to another in Scala

我想在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> = x)。 我想用src列表中的元素替换dest列表的前x个元素。

你的意思是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)

你在程序上思考得太多了,说出你不想怎么做......

怎么样:

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)

如果您想获得更新列表,可以使用列表中的地图。 映射通过将函数应用于列表中的每个元素并返回更新列表来工作。

http://www.brunton-spall.co.uk/post/2011/12/02/map-map-and-flatmap-in-scala/

你可以使用:

if(dest.length <= src.length) dest ::: src.drop(dest.length)
else dest.dropRight(dest.length - src.length) //or throw exception...

也许你想要的东西

 def copy[T](dest: Seq[T], src: Seq[T]): Seq[T] = {
   require(dest.length >= src.length)
   src ++ (dest drop src.length)
 }

我推广到Seq s,但它当然适用于List

如果在运行时未满足,则require方法抛出IllegalArgumentException

然后,您只需要将目标列表的最后( yx )元素附加到源列表(其中x = src.length; y = dest.length)

你可以通过从dest 删除 x元素并将剩余的元素附加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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM