Groovy语言:如何获取两个键值对列表之间的差异?

6
我正在尝试在Groovy语言中从另一个列表中获取一对差异为1的列表。这些pair只是(x,y)坐标,它们是唯一的。 下面是一个简单的示例。请注意,列表可以有数十个pairs。
  def l1 = [[x:1, y:1]]
  def l2 = [[x:0, y:0]]
  println l1 - l2

你将得到[],这是一个空列表,但应该是这样的:[[x:1,y:1]]。

更新:

 for(n in l2) {
   l1 = l1 - n
 }

它能够工作,但是这是一种黑魔法且没有优化。


什么是“差异”?您希望从l1中的相同索引中减去l2中的每个x,y吗?而且您在“对我有用”的示例中使事情更加混乱,因为我怀疑它是否符合您的要求(只保留l1)。 - cfrick
@cfrick 在数学上的区别是:我们从 l1 集合中减去 l2 集合。结果是 = l1 中的所有东西,但不包括 l2 中的。将 (x,y) 视为一个元素,即 (x,y) 在 l1 中但不在 l2 中。这里有一个很好的例子:http://mrhaki.blogspot.ru/2010/08/groovy-goodness-subtracting-map-entries.html - Ivan Voroshilin
ic。[x:0,y:0]这对有点奇怪。如果其中一个不是“falsy”,则使用minus()可以正常工作。 - cfrick
我猜列表可以有重复项,而且它们应该保留? - cfrick
1
如果它们是唯一的,那么l1.toSet()-l2.toSet()可以工作。同时,l1-[[x:1,y:0]]也可以工作。只有[x:0,y:0]会出现一些奇怪的情况。 - cfrick
显示剩余2条评论
1个回答

7

如评论中所述,l1中的对是唯一的(或者说:有唯一结果是可以的),那么您可以将l1 / l2用作集合:

l1 = [[x:1, y:1]]
l2 = [[x:0, y:0]]
println l1.toSet()-l2.toSet()
//; [[x:1, y:1]]

问题最初出在 [x:0,y:0][x:1,y:1]部分。原因在于 public static <T> Collection<T> minus(Collection<T> self, Collection<?> removeMe) 中选取了 n*n 分支,且 NumberAwareComperator 认为这两个映射相等。
def cmp = new org.codehaus.groovy.runtime.NumberAwareComparator()
println cmp.compare(l1[0], l2[0])
//; 0 (equal!)

这其实归结为:
assert [x:1, y:1].hashCode() == [x:0, y:0].hashCode()
    // 120^1 + 121^1 == 120^0 + 121^0

编辑备选方案(如果您可以摆脱地图)

由于这不是很适合基础,您最好使用一个安全的、可比较的类来保存数据。例如:

@groovy.transform.Immutable
class Pair {
    long x,y
}

def p00 = new Pair(0,0)
def p11 = new Pair(1,1)
def p11o = new Pair(1,1)

assert [p00]-[p11] == [p00]
assert [p11]-[p00] == [p11]
assert [p00].intersect([p11]) == []
assert [p11].intersect([p00]) == []
assert [p11].intersect([p11o]) == [p11]
assert [p11].intersect([p11o]) == [p11o]

即使将地图转换为 Expando,效果也更好。

顺便提一下,[[x:0, y:0]].toSet().intersect([[x:1, y:1]]).toSet() 也不起作用,我没有解决方法。最有可能的是我将不得不单独检查这个 0/0 并处理它。 - Ivan Voroshilin
而[x:1,y:1] .hashCode()== [x:0,y:0] .hashCode()让我觉得这是Groovy中的一个错误。他们把它们视为相同的,很奇怪。 - Ivan Voroshilin
@vibneiro,这是Java代码。问题是,NumberAwareComperator是否在使用仅哈希码时进行了太多的快捷方式。基本上,哈希码为120^1 + 121^1 == 120^0 + 121^0。到处都有冲突。 - cfrick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接