将交叉点设置为将某个范围内的值视为相交

时间:2015-12-28 19:17:41

标签: python python-3.x set range set-intersection

我正在尝试计算Python中2组的交集,我想将一定范围内的值(+/- 5)视为相等。例如:

set1 = [22, 570, 233, 127, 92]

set2 = [897, 27, 673, 231, 45]

我想要的是:

len[x for x in set1 if x in set2] == 2

交叉口是22& 27以及233& 231。

有没有一种有效的方法呢?

2 个答案:

答案 0 :(得分:1)

如果“有效”,则表示“短”,当然。

>>> set1 = [22, 570, 233, 127, 92]
>>> set2 = [897, 27, 673, 231, 45]
>>> len([x for x in set1 if any(abs(x-y) <= 5 for y in set2)])
2

如果“有效”意味着“有一个合理的大O运行时间”,那就不那么容易了。上述方法是O(N ^ 2)。你可以得到O(N * log(N))如果你对两个集合进行排序并且并行迭代它们寻找近似匹配,但这并不是完全无关紧要的。

[编辑 - 删除了用于OP输入的O(N log N)代码,但没有用于set1 = [1,3,4]和set2 = [2,10]]

答案 1 :(得分:0)

以记忆为代价,对于小范围(你的例子说+ -5),你可以为检查做更大的set

from itertools import chain

set1 = {22, 570, 233, 127, 92}
set2 = {897, 27, 673, 231, 45}

# Make a frozenset of all values considered overlapping with set2
overlap = 5
overlaprange = range(-overlap, overlap+1)
match2 = frozenset(chain.from_iterable((x + i for i in overlaprange) for x in set2))

print(len(set1 & match2))

这不会多次计算单个元素,如果set2中的值靠得很近,则不会多次存储它们的重叠(转换为frozenset match2 } uniquifies)。如果其中一个set与其他几个set匹配,您可以将重用的set转换为“匹配set”,然后将其用于每次交叉检查结束。