10

Groovy で 2 つのリストを作成するときに、a.intersect(b) と b.intersect(a) を実行すると違いがあるのはなぜですか。

def list1 = ["hello", "world", "world"];
def list2 = ["world", "world", "world"];

println( "Intersect list1 with list2: " + list1.intersect( list2 ) );
println( "Intersect list2 with list1: " + list2.intersect( list1) );

トレース:

Intersect list1 with list2: [world, world, world]
Intersect list2 with list1: [world, world]

(テストしたい場合は、 http: //groovyconsole.appspot.com/からコピーできます)

すべての配列に一意の要素が含まれている場合は、通常どおりに機能します。重複を追加し始めると、奇妙になります。

def list1 = ["hello", "world", "test", "test"];
def list2 = ["world", "world", "world", "test"];

println( "Intersect list1 with list2: " + list1.intersect( list2 ) );
println( "Intersect list2 with list1: " + list2.intersect( list1 ) );

トレース:

Intersect list1 with list2: [world, world, world, test]
Intersect list2 with list1: [world, test, test]

のポイントはintersect()、共通要素を提供することだと思っていたので、どの順序で配置しても問題ありませんでしたか?

そうでない場合、どうすれば共通要素のみを取得できますか (配列内の重複が予想されます)。たとえば、例 1 が返さ["world", "world"]れ、例 2 が返されます。["world", "test"]

編集

少し明確にするために、このコードはユーザー データがまだ同じであることをテストする必要があります (何かの途中で切断され、データが改ざんされていないこと、または以前と同じ状態であることを確認したい場合)。

リストの順序は保証できず (ユーザーは順序を変更できますが、技術的には「同じ」ままです)、重複する可能性があります。

したがって、次のような:["one", "one", "two"]は一致する必要["two", "one", "one"]がありますが、リストへの追加やデータの変更は一致しないはずです。

4

1 に答える 1

14

のソースをCollection.intersect見ると、メソッドのロジックが次のフローに従っていることがわかります。

2 つのコレクションの場合、leftおよびright

  1. より小さい場合leftはスワップrightleftright
  2. すべてをセットに追加left(重複を削除)
  3. の各要素がrightに存在する場合はleftSet、それを結果に追加します

したがって、最後の 2 つの例については、

def array1 = ["hello", "world", "test", "test"]
def array2 = ["world", "world", "world", "test"]

array1.intersect( array2 )(同じアルゴリズムをGroovyで書いた場合):

leftSet = new TreeSet( array1 ) // both same size, so no swap
// leftSet = [ 'hello', 'world', 'test' ]
right   = array2
result = right.findAll { e -> leftSet.contains( e ) }

どちら(実行した場合)は、結果に[world, world, world, test](見つけたように)値があることを意味します。これは、 のすべての要素rightleftSet

ただし、最初の例が返される理由はわかりません["world","world"]...

後で...

したがって、あなたが探しているのは次のようなものだと思います。

def array1 = ["hello", "world", "test", "test"]
def array2 = ["world", "world", "world", "test"]
def intersect1 = array1.intersect( array2 ) as TreeSet
def intersect2 = array2.intersect( array1 ) as TreeSet
assert intersect1 == intersect2

コレクション内の重複に対処するために、 と の両方intersect1intersect2等しくなります。

[test, world]

後でまだ

私はこれがあなたが望むことをすると信じています:

[array1,array2]*.groupBy{it}.with { a, b -> assert a == b }
于 2011-09-12T11:34:53.597 に答える