从字典中选择密钥对的组合

时间:2016-04-12 09:14:24

标签: python dictionary

我有一个字典,其中包含线段的起点和终点坐标。我想比较字典中任意两个键的所有可能组合,以检查线段是否有交集。我怎么能这样做?

v = {1:[(2,3),(10,12)],2:[(22,25),(14,42)],3:[(-8,10),(3,21)]}

确定是否存在碰撞的功能就像这样

def segment_intersect(line1, line2):
    i1 = [min(line1[0][0], line1[1][0]), max(line1[0][0], line1[1][0])]
    i2 = [min(line2[0][0], line2[1][0]), max(line2[0][0], line2[1][0])]
    ia = [max(i1[0], i2[0]), min(i1[1], i2[1])]
    if max(line1[0][0], line1[1][0]) < min(line2[0][0], line2[1][0]):
        return False
    m1 = (line1[1][1] - line1[0][1]) * 1. / (line1[1][0] - line1[0][0]) * 1.
    m2 = (line2[1][1] - line2[0][1]) * 1. / (line2[1][0] - line2[0][0]) * 1.
    if m1 == m2:
        return False
    b1 = line1[0][1] - m1 * line1[0][0]
    b2 = line2[0][1] - m2 * line2[0][0]
    x1 = (b2 - b1) / (m1 - m2)
    if (x1 < max(i1[0], i2[0])) or (x1 > min(i1[1], i2[1])):
        return False
    return True

3 个答案:

答案 0 :(得分:2)

你可以写

comb = ((v[x], v[y]) for x in v for y in v if x < y)

if x < y部分确保您只获得(1,2)而不是(2,1),这将是相同的而不是(1,1),这是没有意义的。

你得到一个带组合的迭代器,你可以写:

for line1, line2 in comb:
    segment_intersect(line1, line2)

请注意,如果密钥为1,2,3,则应使用list而不是dict

答案 1 :(得分:2)

您可以为每个元素元素创建嵌套循环。以下示例仅执行此操作并使用绘图测试结果。

import matplotlib.pyplot as plt
v = {1:[(2,3),(10,12)],2:[(22,25),(14,42)],3:[(-8,10),(3,21)],4:[(10,3),(2,12)]}
keys = list(v.keys())
print(keys)
for i in range(len(keys)):
    for j in range(i+1,len(keys)):
        print(keys[i],keys[j],segment_intersect(v[keys[i]], v[keys[j]]))
    plt.plot(*v[keys[i]],label=str(keys[i]))
plt.legend()
plt.show()

,结果是:

[1, 2, 3, 4]
1 2 False
1 3 False
1 4 True
2 3 False
2 4 False
3 4 False

,并且:

lines and interceptions

答案 2 :(得分:2)

您可以使用标准itertools.combinations功能生成组合。

例如,

from itertools import combinations

for k1, k2 in combinations(v, 2):
    print(k1, k2, segment_intersect(v[k1], v[k2]))

使用itertools.combinations比使用嵌套for循环更有效,更易读,特别是如果你想要长度&gt;的组合。 2。