间隔重叠列表的笛卡尔积

时间:2016-08-06 15:41:01

标签: python

我有两个列表,包括间隔实线

I = [[8,12], [18,24], [3,5]]
J = [[7,10], [2,6], [18,22]] 

我想生成一个列表,其中包含I和J重叠的区间对。例如,列表的一个元素是[[8,12],[7,10]]。我有一个循环来做这个

res=[]
for i in range(len(I)):
    des=[]
    for j in range(len(J)):
        if (I[i][1]<=J[j][1] and I[i][1]>=J[j][0])   or (J[j][1]<=I[i][1] and J[j][1]>=I[i][0]):

             z=[I[i],J[j]]
             res.append(z) 

产生

res=[[[8, 12], [7, 10]], [[18, 24], [18, 22]], [[3, 5], [2, 6]]]

但我正在努力寻找更清洁更有效的版本

每个单独的列表中可能有重叠的间隔。例如,我们可以

I= [ [2,5], [1,4] ]

J= [[3,7], [10,12]]

在这种情况下,结果列表为

[ [[1,4], [3,7]], [[2,5],[3,7]]

2 个答案:

答案 0 :(得分:0)

通过使用enumerate同时拉出索引和值,可以使这更具可读性。此外,在语义上,数字对可能更好地描述为元组。

I = [(8,12), (18,24), (3,5)]
J = [(7,10), (2,6), (18,22)]

def overlap(I, J):
    res=[]
    for i, ival in enumerate(I):
        for j, jval in enumerate(J):
            if (ival[1]<=jval[1] and ival[1]>=jval[0]) or (jval[1]<=ival[1] and jval[1]>=ival[0]):
                 z = (ival, jval)
                 res.append(z)
    return res

res = overlap(I, J)
print(res)
assert res == [((8, 12), (7, 10)), ((18, 24), (18, 22)), ((3, 5), (2, 6))]

但由于索引不必使用,只需循环遍历值即可进一步简化。

def overlap(I, J):
    res=[]
    for ival in I:
        for jval in J:
            if (ival[1]<=jval[1] and ival[1]>=jval[0]) or (jval[1]<=ival[1] and jval[1]>=ival[0]):
                 z = (ival, jval)
                 res.append(z)
    return res

答案 1 :(得分:-1)

这应该

import itertools

I = [[8,12], [18,24], [3,5]]
J = [[7,10], [2,6], [18,22]]

z = []
for x,y in itertools.product(I,J):  
        #find intersection via sets 
        if set(range(x[0],x[1])) & set(range(y[0],y[1])):
            z.append([x,y])

print z