Copy items from one list to another in Scala

I would like to create a universal (invariant) method in Scala that copies elements from the source list to the destination list. In Java, there is a copy method in java.util.Collections (see http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html#copy%28java.util.List, % 20java.util.List% 29 ). I know that Scala List is an immutable object, so I would like to create and return a new list.

I wrote the following code:

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 } } 

But I think it could be written better. Could you help me write the best code? Thanks in advance.

EDITED . Perhaps I expressed the unclear what I want to do. I have two lists (scala.collection.immutable.List), for example. src (length = x) and dest (length = y> = x ). I would like to replace the first x elements of the dest list with the elements from the src list.

+4
source share
5 answers

If you want an updated list, you can use the map on your list. The map works by applying a function to each item in the list and returning an updated list.

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

+3
source

Do you mean scala.collection.immutable.List ? This is unchanging. No need to copy them. Immutable means that nothing can change it, so you can use it in different threads.

The general way to create collections in scala is through the builder. You can get one from the CanBuildFrom object. Alternatively, you can get it from the genericBuilder collection instance method.

 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) 

If you want to create a new collection of a different type based on an existing collection, you can use collection.breakOut mid like this:

 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) 
+8
source

You think too much about the procedure, say what you don’t want, how to do it ...

What about:

 val src = List(1,2,3) val dest = src map {x => x} 

if you really want to make it a function

 def copy[T](src: List[T]): List[T] = src map {x => x} 

in response to the OP update: (which was also suggested by others)

 def copy[T](src: List[T], dest: List[T]): List[T] = src ++ dest.drop(src.length) 
+3
source

You can use:

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

Maybe you want something like

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

I am generalized to Seq s, but it works on List s, of course

The require method throws an IllegalArgumentException if not executed at run time

Then you only need to add the last ( yx ) elements of the destination list in the Source list (where x = src.length; y = dest.length)

You do this by discarding x elements from dest and adding the remaining to src .

This is what you get from 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) 
+1
source

All Articles