假设我有一个列表,如下所示:
l = [[1,2,3],[6,5,4,3,7,2],[4,3,2,9],[6,7],[5,1,0],[6,3,2,7]]
我如何编写python代码来检查是否有总是一起出现的元素?例如,在上面的例子中,2,3和6,7总是出现在相同的列表中。 (可能还有其他人,不确定)。
实现这一目标的最简单方法是什么?
我唯一的想法是转换 inner-list1 设置和检查交集 inner-list2 但是当我检查交叉路口时 inner-list3,这些元素可能根本不会发生 inner-list3。
我可以这样做:
for i in range(0,len(lists)):
a=set(lists[i]).intersection(lists[i+1])
if (len(a))==0:
continue
else:
a.intersection(lists[i+1])
这当然不起作用,但我怎么能正式编码这个或者有更好的方法吗?
运用 itertools.combinations:
我最初想过用的东西 itertools.combination, 但正如这允许的那样 elements 从一个 list 它们不是彼此相邻的,它不适用于我想到的解决方案。
事实证明,当看非数字输入时 lists, itertools.combinations 是 两种情况都是必要的。我很困惑,因为我认为了 groups 必须是 adjacent。
我认为最适合这种方式的方法是产生可能的方法 elements 那 可以 工作,然后检查每一个 function 反对这 list 的 sub-lists - 而不是做某种组合工作 list 沿着那条路走下去。
所以要检查一下 list 可能的 elements 是'有效',即如果全部 elements 只发生在一起,我用的很简单 if 用发电机 all() 和 any() 内建的 functions 做这部分工作。
现在这是有效的,需要有一种产生潜力的方法 elements 可能会发生。我刚刚用两个嵌套做了这个 for-loops - 一个 iterating 过了 width 的 window和一个 iterating 在哪里 start 的 window 是。
然后从这里,我们只检查那组 elements 是 valid 并将其添加到另一个 list 如果是!
import itertools
def valid(p):
for s in l:
if any(e in s for e in p) and not all(e in s for e in p):
return False
return True
l = [[1,2,3],[6,5,4,3,7,2],[4,3,2,9],[6,7],[5,1,0],[6,3,2,7]]
els = list(set(b for a in l for b in a))
sol = []
for w in range(2,len(els)+1):
for c in itertools.combinations(els, w):
if valid(c):
sol.append(c)
这使 sol 如:
[(2, 3), (6, 7)]]
这些 2 nested for-loops 实际上可以被扔到一起很好 one-liner (不确定其他人是否认为它是Pythonic):
sol = [c for w in range(2, len(els)+1) for c in itertools.combinations(els, w) if valid(c)]
它的工作原理相同但只是更短。
由于受欢迎的需求(@Arman),我已经更新了答案,现在它应该适用于其他人 elements 除了 0-9。这是通过引入一个独特的 elements list (els)。
还有一些测试来自 @thanasisp 使用上面相同的代码:
l = [[1, 3, 5, 7],[1, 3, 5, 7]]
给 sol 如:
[(1, 3), (1, 5), (1, 7), (3, 5), (3, 7), (5, 7), (1, 3, 5), (1, 3, 7), (1, 5, 7), (3, 5, 7), (1, 3, 5, 7)]
并再次:
l = [[1, 2, 3, 5, 7], [1, 3, 5, 7]]
得到:
[(1, 3), (1, 5), (1, 7), (3, 5), (3, 7), (5, 7), (1, 3, 5), (1, 3, 7), (1, 5, 7), (3, 5, 7), (1, 3, 5, 7)]
我相信这是正确的 2 不能 像其他所有人一样在任何群体中 elements 是一个不同的 sub-list,所以它永远不能与另一个组成一个团体 element。
另一个具有默认dicts的线性解决方案(元组可用于制作可用密钥):
from collections import defaultdict
isin,contains = defaultdict(list),defaultdict(list)
for i,s in enumerate(l):
for k in s :
isin[k].append(i)
# isin is {1: [0, 4], 2: [0, 1, 2, 5], 3: [0, 1, 2, 5], 6: [1, 3, 5],
# 5: [1, 4], 4: [1, 2], 7: [1, 3, 5], 9: [2], 0: [4]}
# element 1 is in sets numbered 0 and 4, and so on.
for k,ss in isin.items():
contains[tuple(ss)].append(k)
# contains is {(0, 4): [1], (0, 1, 2, 5): [2, 3], (1, 3, 5): [6, 7],
# (1, 4): [5], (1, 2): [4], (2,): [9], (4,): [0]})
# sets 0 and 4 contains 1, and no other contain 1.
现在,如果您查找按组显示的元素 n (n=2 在这里),键入:
print ([p for p in contains.values() if len(p)==n])
# [[2, 3], [6, 7]]