4

ソース リストから宛先リストに要素をコピーする汎用 (不変) メソッドを 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
    } 
}

でも、もっと上手に書けると思います。より良いコードを書くのを手伝ってくれませんか? 前もって感謝します。

EDITED : たぶん、私が何をしたいのかがはっきりしていません。2 つのリスト (scala.collection.immutable.List) があります。たとえば、src (長さ = x) とdest (長さ = y>=x) です。destリストの最初のx要素をsrcリストの要素に置き換えたいと思います。

4

5 に答える 5

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次のようにメソッドを使用できます。

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

更新

require(src.length <= dest.length, "IndexOutOfBoundsException")
src ++ dest.drop(src.length)
于 2012-12-10T12:52:13.600 に答える
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)
于 2012-12-10T12:58:28.423 に答える
3

更新されたリストを取得したい場合は、リストでマップを使用できます。Map は、リスト内の各要素に関数を適用し、更新されたリストを返すことによって機能します。

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

于 2012-12-10T13:01:24.583 に答える
2

あなたが使用することができます:

if(dest.length <= src.length) dest ::: src.drop(dest.length)
else dest.dropRight(dest.length - src.length) //or throw exception...
于 2012-12-10T12:31:02.163 に答える
1

多分あなたは次のようなものが欲しい

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

sに一般化しましたが、もちろん sSeqでも動作しますList

実行時に満たされない場合、メソッドrequireはスローしますIllegalArgumentException

y-x次に、宛先リストの最後の ( ) 要素をソース リストに追加するだけで済みます (x = src.length; y = dest.length)。

これを行うには、から要素を削除 し、残りを に追加ます。xdestsrc

これは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)
于 2012-12-10T14:00:03.273 に答える