Groovy: разница с a.пересечение(b) и b.пересечение (a)
почему в Groovy, когда я создаю 2 списка, есть разница,если я делаю.пересечение( b) и b.пересечение (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()
должен был дать вам общие элементы, поэтому не имело значения, в каком порядке вы их помещаете?
если это не так, как я могу получить только общие элементы (ожидать дубликатов в массиве). Е. Г. пример один должен вернуть ["world", "world"]
и пример два должен вернуть ["world", "test"]
редактировать
чтобы уточнить немного, этот код должен проверить, что пользовательские данные по-прежнему одинаковы (предполагая, что они отключены в середине чего-то, и мы хотите убедиться, что данные не были изменены или находятся в том же состоянии, что и раньше).
порядок списков не может быть гарантирован (пользователь может изменить его порядок, но он по-прежнему технически "тот же"), и дубликаты возможны.
что-то вроде: ["one", "one", "two"]
должны соответствовать ["two", "one", "one"]
, тогда как любое дополнение к спискам или изменение данных не должно совпадать.
1 ответов
если вы посмотрите на источник Collection.intersect
, вы можете видеть, что логика метода следует этому потоку:
для двух коллекций, left
и right
- обмен
left
иright
еслиleft
меньше, чемright
- добавить
left
в набор (удаляет дубликаты) - для каждого элемента
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]
(как вы нашли). Это потому, что каждый элемент right
можно найти в leftSet
не уверен, почему первый пример должен вернуться ["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
для того, чтобы вы справлялись с дубликатами в коллекциях, как тогда оба intersect1
и intersect2
будет равна
[test, world]
позже еще
я считаю, что это делает то, что вы хотите:
[array1,array2]*.groupBy{it}.with { a, b -> assert a == b }