繁体   English   中英

在范围列表中查找序列

[英]Find sequences in list of ranges

我有一个包含范围信息的随机长度列表:

list = [
 [[7, 12], [6, 12], [38, 44], [25, 30], [25, 29]], 
 [[0, 5], [1, 5], [2, 5], [12, 16], [13, 16], [20, 23], [29, 33], [30, 33]], 
 [[5, 7], [6, 8], [7, 9], [8, 10], [9, 11], [10, 12], [16, 18], [17, 19], [18, 20], [23, 25], [24, 26], [25, 27], [26, 28], [27, 29], [33, 35], [34, 36], [35, 37], [36, 38], [37, 39], [38, 40], [39, 41], [40, 42], [41, 43], [42, 44]]
]

例如,第一个元素[[7, 12], [6, 12], [38, 44], [25, 30]]包含 4 个范围 7-12, 6-12, 38-44 和 25-30 等。

我需要找到长度给定列表长度的所有可能的链(链是一个连续范围的数组,其中第一个范围的结束==下一个范围的开始),因为我可以并且应该从每行中只取一个范围行的确切顺序。

因此,对于这个示例列表:链将是[[6, 12], [12, 16], [16, 18]] , [[7, 12], [12, 16], [16, 18]] , [[25, 30], [30, 33], [33, 35]][[25, 29], [29, 33], [33, 35]]

现在我坚持使用超过三个长度的列表,无法提出递归解决方案。

您可以使用itertools.product迭代所有可能的链(每个“行”中 1 个范围的所有组合),

然后通过检查特定链是否合法的简单 function 过滤它们。

尝试这个:

from itertools import product

def check_chain(chain):
    prev_end = chain[0][1]
    for start, end in chain[1:]:
        if start != prev_end:
            return False
        prev_end = end
    return True

all_candidate_chains = product(*list)

result = [[*chain] for chain in all_candidate_chains if check_chain(chain)]

print(result)

Output:

[[[7, 12], [12, 16], [16, 18]], [[6, 12], [12, 16], [16, 18]], [[25, 30], [30, 33], [33, 35]]]

编辑:

也可以使用zipall用 1-liner 替换check_chain

from itertools import product
result = [[*chain] for chain in product(*list) if all(end1 == start2 for (_, end1), (start2, _) in zip(chain, chain[1:]))]
print(result)

您可以在不查看所有排列的情况下执行此操作。 从最后一项开始并制作一个字典,其中键是字典中的第一个值。 然后通过列表向后工作,并根据添加到数组中的元组的第二个值查找前一个键,如 go:

最后,您将有一个字典,键为第一个列表的元组中的第一个值。 此时您可以将值展平。

在这里,我在中间列表中添加了一对[12,9] ,以便我可以看到它与分支路径一起使用:

from collections import defaultdict
from itertools import chain

l = [
 [[7, 12], [6, 12], [38, 44], [25, 30]], 
 [[0, 5], [1, 5], [2, 5], [12, 16], [12, 9],[13, 16], [20, 23], [29, 33], [30, 33]], 
 [[5, 7], [6, 8], [7, 9], [8, 10], [9, 11], [10, 12], [16, 18], [17, 19], [18, 20], [23, 25], [24, 26], [25, 27], [26, 28], [27, 29], [33, 35], [34, 36], [35, 37], [36, 38], [37, 39], [38, 40], [39, 41], [40, 42], [41, 43], [42, 44]]
]


d = defaultdict(list)
for k, v in l[-1]:
    d[k].append([[k,v]])

for sub in reversed(l[:-1]):
    ds = defaultdict(list)
    for k, v in sub:
        if v in d:
            ds[k].extend([[k,v], *v2] for v2 in d[v] )
    d = ds

list(chain.from_iterable(d.values()))

Output:

[[[7, 12], [12, 16], [16, 18]],
 [[7, 12], [12, 9], [9, 11]],
 [[6, 12], [12, 16], [16, 18]],
 [[6, 12], [12, 9], [9, 11]],
 [[25, 30], [30, 33], [33, 35]]]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM