16

Scalaでリストを浅くコピーしたい。

私は次のような何かをしたかった:

val myList = List("foo", "bar")
val myListCopy = myList.clone

ただし、cloneメソッドは保護されています。

4

3 に答える 3

18

ここに答えはありません:そうしないでください。AListは不変であるため、コピーしてもまったく意味がありません。

いくつかの操作を考えてみましょう。

val list = List(1,2,3)
val l1 = 0 :: list
val l2 = "a" :: list

どちらl1l2変更listしていませんが、どちらもを参照する新しいリストを作成しますlist

これを詳しく説明しましょう。コンストラクターList(1,2,3)は3つの要素を作成し、シングルトンオブジェクトも使用しています。具体的には、次の要素をインスタンス化しています。

::(3, Nil)
::(2, reference to the previous element)
::(1, reference to the previous element)

そしてNil、シングルトンオブジェクトです。識別子listが実際に指しているのは、その最後の要素です。

ここで、に割り当てる0 :: listl1、1つの新しいオブジェクトがインスタンス化されます。

::(0, reference to ::(1, etc))

もちろん、への参照があるので、4つの要素(または、数える場合は5つ)のリストlistと考えることができます。l1Nil

l2は同じタイプではありませんがlist、それも参照しています!ここ:

::("a", reference to ::(1, etc))

ただし、これらすべてのオブジェクトに関する重要な点は、変更できないことです。セッターも、プロパティを変更するメソッドもありません。それらは、「ヘッド」(これを最初の要素と呼びます)に同じ値/参照を持ち、「テール」(これを2番目の要素と呼びます)に同じ参照を持ちます。

ただし、リストを変更しているように見えるメソッドがあります。ただし、新しいリストを作成しているので安心してください。例えば:

val l3 = list map (n => n + 1)

メソッドマップは、同じサイズの完全に新しいリストを作成します。このリストでは、の対応する要素から新しい要素を計算できlistます(ただし、古い要素も無視できます)。

val l4 = l2 filter (n => n.isInstanceOf[Int])

l4と同じ要素がありますが(listただしタイプは異なります)、まったく新しいリストでもあります。このメソッドfilterは、渡したルールに基づいて新しいリストを作成し、どの要素が入り、何が入らないかを示します。既存のリストを返す可能性がある場合に備えて、最適化を試みません。

val l5 = list.tail

これは新しいリストを作成しません。l5代わりに、の既存の要素に割り当てるだけですlist

val l6 = list drop 2

繰り返しますが、新しいリストは作成されません。

val l7 = list take 1

ただし、これは新しいリストを作成します。これは、の最初の要素を変更しlistて、テールがを指すようにすることができないためNilです。

実装の詳細は次のとおりです。

  • List抽象クラスです。::これには、クラス(はい、それはクラスの名前です)とシングルトンオブジェクトの2つの子孫がありますNilListは封印されているため、新しいサブクラスを追加することはできません。また::、finalであるため、サブクラス化することはできません。

  • リストを変更するために何もすることはできませんが、一部の操作では内部的に可変状態を使用します。これはパフォーマンスに役立ちますが、ローカライズされているため、作成したプログラムがそれを検出したり、結果を被ったりすることはありません。他の関数がリストをどのように処理するか、またはリストを同時に使用しているスレッドの数に関係なく、必要に応じてリストを渡すことができます。

于 2009-09-18T22:33:24.767 に答える
5

リストをフィルタリングするには:

val list = List(1,2,3,4,5)
//only evens
val evens = list.filter(e=>e%2 == 0)

println(list)
//--> List(1, 2, 3, 4, 5)

println(evens) 
//--> List(2, 4)

ワイルドカードを使用して、いくつかの文字を保存することもできます。

val evens = list.filter(_%2==0)

上でコメントしたように、リストは不変であることに注意してください。つまり、これらの操作は元のリストを変更せず、実際に新しいリストを作成します。

于 2009-09-18T18:42:58.360 に答える
0

:_ *タイプアノテーションを使用

scala> val l1 = List(1,2,3)
l1: List[Int] = List(1, 2, 3)

scala> val l2 = List(l1:_*)
l2: List[Int] = List(1, 2, 3)

アノテーションに関する詳細:Scala:Seqまたはvarargsのいずれかをとるコンストラクター

于 2021-09-30T06:39:37.897 に答える