如何在python中与索引相关的列表相交
我知道这个问题看起来像是重复的。但我很难解决这个问题,也找不到一个有帮助的解决方案 我正在用python实现一个遗传算法来解决旅行商问题 假设我们有这些名单(旅游) 如您所见,[5,4]在整个3个列表中重复出现 一个常规的交集将返回列表中的所有元素 我想要一些函数,比如intersect_list(a,b) 返回[5,4] 有python内置的方法可以找到这个吗?或者你有什么建议吗 注意:我知道我可以循环它来解决这个问题,但请记住,在我的例子中,我有大约400个列表。每个人的长度是401 换句话说:我希望看到这些列表之间的公共路径 如果有什么不清楚的地方,请告诉我如何在python中与索引相关的列表相交,python,list,Python,List,我知道这个问题看起来像是重复的。但我很难解决这个问题,也找不到一个有帮助的解决方案 我正在用python实现一个遗传算法来解决旅行商问题 假设我们有这些名单(旅游) 如您所见,[5,4]在整个3个列表中重复出现 一个常规的交集将返回列表中的所有元素 我想要一些函数,比如intersect_list(a,b) 返回[5,4] 有python内置的方法可以找到这个吗?或者你有什么建议吗 注意:我知道我可以循环它来解决这个问题,但请记住,在我的例子中,我有大约400个列表。每个人的长度是401 换句话
提前谢谢 一个想法是,您可以使用
",".join(list)
然后将问题转化为两个字符串中最长的匹配子字符串
关于此问题的解决方案和讨论,请访问:
您可以使用list函数将它们压缩成元组,并返回所有元素相同的元组
a = [1,0,2,5,4,3,1]
b = [1,2,5,4,3,0,1]
c = [1,3,5,4,2,0,1]
zipped_tuples = zip(a, b, c)
您可以尝试利用这一点来获得位置交点。400长度为400的列表不是太大的问题。首先将每个序列分解为其所有可能的子序列,(长度
N
的列表大约有0.5*N**2
可能的子序列)。然后将它们全部相交,取最长的一个
a = [1,0,2,5,4,3,1]
b = [1,2,5,4,3,0,1]
c = [1,3,5,4,2,0,1]
def longest_match_finder(lists):
matches = []
for a in lists:
lengths = set()
for leng in xrange(1,len(a)+1):
lengths = lengths | set(tuple(a[i:i+leng])
for i in xrange(len(a)-leng+1))
matches.append(lengths)
return max(set.intersection(*matches), key=len)
print longest_match_finder([a,b,c])
#Output:
(5, 4)
使用400
列出每个400
元素,这大约需要280秒(在我非常旧的机器上)。但是,如果我们只对一个列表使用相同的方法,但使用str(list).strip(“[]”)
将其子序列和所有其他列表转换为字符串(由@pyfunc首先发布),我们可以更快地搜索。相同的测试在21秒内运行
:
import ast
def longest_match_finder_2(lists):
a = lists[0]
lengths = set()
for leng in xrange(1,len(a)+1):
lengths = lengths | set(str(a[i:i+leng]).strip('[]')
for i in xrange(len(a)-leng+1))
for seq in lengths.copy():
if not all([seq in str(i).strip('[]') for i in lists[1:]]):
lengths.remove(seq)
return ast.literal_eval(max(lengths, key=len))
我们可以使用ast.literal\u eval()
在最后(安全地)获取一个列表。在查看了@pyfunc发布的链接后,我得出了以下结论:
def shortest_of(lists):
return min(lists, key=len)
def contains_sublist(lst, sublst):
n = len(sublst)
return any((sublst == lst[i:i+n]) for i in xrange(len(lst)-n+1))
def longest_common(lists):
if not lists:
return ()
res = set()
base = shortest_of(lists)
length = len(base)
for i in xrange(length, 0, -1):
for j in xrange(length - i + 1):
candidate = ', ' + str(base[j:i+j]).strip('[]') + ','
#candidate = base[j:i+j]
for alist in lists:
if not candidate in ', ' + str(alist).strip('[]') + ',':
#if not contains_sublist(alist, candidate):
break
else:
res.add(tuple([int(a) for a in candidate[2:-1].split(',')]))
#res.add(tuple(candidate))
if res:
return tuple(res)
return ()
if __name__ == '__main__':
a = [1,0,2,5,4,3,1]
b = [1,2,5,4,3,0,1]
c = [1,3,5,4,2,0,1]
print longest_common([a,b,c])
print longest_common([b,c])
输出:
((5, 4),)
((0, 1), (5, 4))
编辑:
更新了使用字符串转换和匹配的解决方案,因为它碰巧快多了。以前的解决方案部分已注释掉。而且,它现在提供了所有的可能性 因此,澄清一下,您想要两个或更多项目在两个列表中以相同的顺序运行?所有列表都是彼此的输入排列吗?为什么不应该与列表(a,b)
相交\u list(a,b)
return[2,5,4,3]
?我觉得这是一个最长的常见连续子序列问题。为什么要转换为字符串?最长子字符串的算法适用于相同的列表way@JBernardo:是的,我在考虑最大的子串,因此得到了答案。我会更正它。这不起作用,因为子序列的索引不一定相同。有一个问题,请尝试最长匹配查找器([a,b])
,输出是(5,4,3)
,而它应该是(2,5,4,3)
@Amr-谢谢,修复了它。愚蠢地将最大值视为大小而不是长度!我更新了我的代码,我的代码也使用了字符串。但是有一个小问题,例如:[1,2,3]
将是'1,2,3'
,它将匹配[11,2,3]
'11,2,3'
。我也爱上了:)@Amr-是的,我注意到,就在我意识到我太累了,应该上床睡觉的时候:)很好,从大到小检查,不做所有的前期工作(就像我做的那样),会让事情变得更快:)是的,但我认为如果最大的公共子列表包含很少的元素,我的会更慢。我不擅长基准测试,所以我没有尝试过。@Amr:很高兴看到你解决了这个问题并把答案发回来了
((5, 4),)
((0, 1), (5, 4))