Groovy:与a.interters(b)和b.intersect(a)的区别 [英] Groovy: Difference with a.intersect( b ) and b.intersect( a )

查看:197
本文介绍了Groovy:与a.interters(b)和b.intersect(a)的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么在Groovy中,当我创建2个列表时,如果我执行a.intersect(b)和b.intersect(a),有什么区别:

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

println(与list2相交的list1:+ list1.intersect(list2));
println(与list1相交的list2:+ list2.intersect(list1));

痕迹:

  list1与list2相交:[world,world,world] 
与list1相交的list2:[world,world]

(您可以在这里复制它: http://groovyconsole.appspot.com/ 如果你想测试它)



如果数组都包含唯一元素,那么它正常工作。一旦你开始添加重复项,它会变得奇怪:

  def list1 = [hello,world,test ,测试]; 
def list2 = [world,world,world,test];

println(与list2相交的list1:+ list1.intersect(list2));
println(与list1相交的list2:+ list2.intersect(list1));

痕迹:

  list1与list2相交:[world,world,world,test] 
与list1相交的list2:[world,test,test]

我认为 intersect()的整点是为了给你共同的元素,所以它没关系你把他们放在哪个订单?



如果不是这种情况,我怎么才能得到通用元素(期望数组中有重复)。例如。例子之一应该返回 [world,world] ,例子2应该返回 [world,test] $ b

编辑

为了澄清一下,这段代码应该测试那用户数据仍然是相同的(假设他们在中间断开连接,我们希望确保数据没有被篡改,或者与以前一样)。



列表的顺序不能保证(用户可以重新排序,但它在技术上仍然是相同的),并且可能有重复。



因此,如下所示: [one,one,two] 应该匹配 [two,one one] ,而列表中的任何附加内容或数据中的更改都不应匹配。

如果你看 Collection.intersect 的源代码,您可以看到该方法的逻辑遵循此流程:



为两个集合, left right


  1. 交换 if left 小于

  2. 添加所有剩下到一个Set中(删除重复)
  3. 对于右边的每个元素 leftSet 中,然后将其添加到结果中

最后2个例子;

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

array1.intersect(array2)会给(如果我们在Groovy中写了相同的算法):

  leftSet = new TreeSet(array1)//两者大小相同,所以不交换
// leftSet = ['hello',' world','test']
right = array2
result = right.findAll {e - > leftSet.contains(e)}

其中(如果运行它),您可以看到意味着结果值 [世界,世界,世界,测试] (如您所见)。这是因为 right 中的每个元素都可以在 leftSet

中找到

不知道为什么第一个例子应该返回 [world,world] 尽管...



稍后...



所以,我认为你正在寻找的是这样的:



< pre $ 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  - >断言a == b} 


Why in Groovy, when I create 2 lists, is there a difference if I do a.intersect( b ) and 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) );

traces:

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

(you can copy it here: http://groovyconsole.appspot.com/ if you want to test it)

If the arrays all contain unique elements, then it works as normal. Once you begin to add duplicates, it gets weird:

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 ) );

traces:

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

I thought the whole point of intersect() was to give you the common elements, so it didn't matter which order you put them in?

If this isn't the case, how can I get only the common elements (expect duplicates in the array). E.g. example one should return ["world", "world"] and example two should return ["world", "test"]

Edit

To clarify a bit, this code should test that user data is still the same (assuming they disconnected in the middle of something and we want to make sure the data hasn't been tampered with, or is in the same state as before).

The order of the lists can't be guaranteed (the user could reorder it, but it's still technically the "same"), and duplicates are possible.

So something like: ["one", "one", "two"] should match ["two", "one", "one"], whereas any addition to the lists, or change in data shouldn't match.

解决方案

If you look at the source for Collection.intersect, you can see that the logic of the method follows this flow:

for two collections, left and right

  1. Swap left and right if left is smaller than right
  2. Add all of left into a Set (removes duplicates)
  3. For each element in right if it exists in the leftSet, then add it to the results

So, for your last 2 examples;

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

array1.intersect( array2 ) would give (if we wrote that same algorithm in Groovy):

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

Which (if you run it), you can see means result has the value [world, world, world, test] (as you found). This is because every element in right can be found in the leftSet

Not sure why the first example should return ["world","world"] though...

later...

So, what I think you are looking for would be something like this:

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

in order that you cope with the duplicates in the collections, as then both intersect1 and intersect2 will be equal to

[test, world]

later still

I believe this does what you want:

[array1,array2]*.groupBy{it}.with { a, b -> assert a == b }

这篇关于Groovy:与a.interters(b)和b.intersect(a)的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆