来自不同数字列表的第一个公共元素

First common element from different lists of numbers

我正在尝试从例如5 个单独的号码列表。 例如5个号码列表是这些

list_1 = [13579875, 25732, 3541, 56732, 1567, 20546, 10, 68971]
list_2 = [1856721, 25724, 3541, 56732, 1567, 20546, 10, 68971]
list_3 = [2354074, 25732, 3541, 56732, 1567, 20546, 10, 68971]
list_4 = [533878, 651, 658, 8654,1357, 1254, 9, 68971]
list_5 = [567432, 25732, 3541, 56732, 1567, 20546, 10, 68971]

所以最终,我想一次获取一对列表并检查他们的 FCN 是什么。在我看来,我需要找到第一场比赛的索引。所以在 list_1 和 list_2 之间,FCN 是 3541(list_1 的索引 2 和 list_2 的索引 2)。然后我必须比较 list_1 和 list_3 并找到它们的 FCN,即 25732。在任何时候,我都必须记住比较列表对的 FCN。构建显示数字关联的树的最终目的。然后在将 list_1 与所有列表进行比较 list_5 之后,我将开始将 list_2 与所有其他列表进行比较,直到完成所有可能的比较。

我想过用两个 for 循环来解决它,但我无法将它们组合成一个函数。这就是我的全部:

compare_lists = []
for i in list_1: 
       if i in list_2:
           compare_lists.append(1)
       else: 
           compare_lists.append(0)
print compare_lists

对于我找到 FCN 索引的部分,我有这个:

indexFCN_a = ""
indexFCN_b = ""
for a in list_1:
    if a in list_2: 
        indexFCN_a = list_1.index(a)
        indexFCN_b = list_2.index(a)
        print indexFCN_a
        break

显然,我的主要问题之一是这些需要在一个函数中,我不太确定如何正确地做到这一点。我试过了,但它是不完全是应该的。 你能在函数中给出答案吗?如有任何帮助,我们将不胜感激。

我相信这个任务可以更有效地解决,所以如果您有任何想法,请分享。请记住,最终目的是为每次比较存储 FCN,以构建显示数字关联的树。

请参阅评论以获取更多说明。 另外:我怎么能跟踪一个元素是 FCN 的次数?所以这个问题的预期输出是:3541 - 3 次,25732 - 3 次,68971 - 4 次。

您可以使用 itertools.combination 获取所需的对并使用 izip 压缩您的列表并比较同一索引中的元素。

还有一种更优雅的方式,您可以将列表放入字典中,如下所示:

d={
'list_1':[13579875, 25732, 3541, 56732, 1567, 20546, 10, 68971],
'list_2' : [1856721, 25724, 3541, 56732, 1567, 20546, 10, 68971],
'list_3' : [2354074, 25732, 3541, 56732, 1567, 20546, 10, 68971],
'list_4' : [533878, 651, 658, 8654,1357, 1254, 9, 68971],
'list_5' : [567432, 25732, 3541, 56732, 1567, 20546, 10, 68971]}

names=['list_1','list_2','list_3','list_4','list_5']
from itertools import combinations,izip
for i,j in combinations(names,2):
  for k,t in izip(d[i],d[j]):
    if k==t:
        print (i,j),'value:{}-index:{}'.format(k,d[i].index(k))
        break

结果:

('list_1', 'list_2') value:3541-index:2
('list_1', 'list_3') value:25732-index:1
('list_1', 'list_4') value:68971-index:7
('list_1', 'list_5') value:25732-index:1
('list_2', 'list_3') value:3541-index:2
('list_2', 'list_4') value:68971-index:7
('list_2', 'list_5') value:3541-index:2
('list_3', 'list_4') value:68971-index:7
('list_3', 'list_5') value:25732-index:1
('list_4', 'list_5') value:68971-index:7

注意:zip 函数将为您提供给定迭代的列,例如,itertools.izip 类似于 zip 但它 returns 是一个列生成器,而不是列表:

>>> l1=['a','b','c']
>>> l2=[1, 2, 3]
>>> zip(l1,l2)
[('a', 1), ('b', 2), ('c', 3)]

所以经过长时间的讨论,如果你想获得相同元素的数量,你可以使用 collections.Counter 并使用 Counter.most_common(N) 来获得最常见的 N 项:

d={
'list_1':[13579875, 25732, 3541, 56732, 1567, 20546, 10, 68971],
'list_2' : [1856721, 25724, 3541, 56732, 1567, 20546, 10, 68971],
'list_3' : [2354074, 25732, 3541, 56732, 1567, 20546, 10, 68971],
'list_4' : [533878, 651, 658, 8654,1357, 1254, 9, 68971],
'list_5' : [567432, 25732, 3541, 56732, 1567, 20546, 10, 68971]}

names=['list_1','list_2','list_3','list_4','list_5']
from itertools import combinations
from collections import Counter
CNT=Counter()
for i,j in combinations(names,2):
  for k,t in zip(d[i],d[j]):
    if k==t:
        CNT.update([k])
        break
print CNT
print CNT.most_common(1)

结果:

Counter({68971: 4, 25732: 3, 3541: 3})
[(68971, 4)]

如果你不想要不同索引中的相等元素但是拳头匹配你可以使用下面的代码:

d={
'list_1':[13579875, 25732, 3541, 56732, 1567, 20546],
'list_2' : [1856721, 25724, 56732,3541, 1567, 20546,3541, 10, 68971],
'list_3' : [2354074, 25732, 3541, 56732, 1567, 20546, 10, 68971],
'list_4' : [533878, 651, 658, 8654,1357, 1254],
'list_5' : [567432, 25732, 3541, 56732, 20546, 10, 68971]}

names=['list_1','list_2','list_3','list_4','list_5']
from itertools import combinations,izip
for i,j in combinations(names,2):
  for ind,k in enumerate(d[i]):
    if k in d[j]:
        print (i,j),'value:{}-index for {}:{},index for {}:{}'.format(k,i,ind,j,d[j].index(k))
        break

结果:

('list_1', 'list_2') value:3541-index for list_1:2,index for list_2:3
('list_1', 'list_3') value:25732-index for list_1:1,index for list_3:1
('list_1', 'list_5') value:25732-index for list_1:1,index for list_5:1
('list_2', 'list_3') value:56732-index for list_2:2,index for list_3:3
('list_2', 'list_5') value:56732-index for list_2:2,index for list_5:3
('list_3', 'list_5') value:25732-index for list_3:1,index for list_5:1
[Finished in 0.7s]

下面的怎么样?

我假设了一些事情 - 所有列表的长度都相等。那么在那种情况下就像 -

filter(lambda (a,b): a == b, zip(list_1, list_2))[0][0] 

编辑: 您可以对列表的所有组合执行上述操作

from itertools import combinations
min = 1000000000000 # some very large number
for x,y in combinations((list_1, list_2, list_3, list_4, list_5), 2):
    min_2 = filter(lambda (a,b): a == b, zip(x, y))[0][0]
    print min_2
    if min_2 < min: 
        min = min_2 

print min

下面应该给你你想要的

基本上,一个元素一个元素地比较。如果它们相等,我们收集它们,然后在索引 0 处获取元组的第一个元素。

这是你想要的吗?

您可以先对列表进行排序,然后使用二分法:

list_1 = [13579875, 25732, 3541, 56732, 1567, 20546, 10, 68971]
list_2 = [1856721, 25724, 3541, 56732, 1567, 20546, 10, 68971]
list_3 = [2354074, 25732, 3541, 56732, 1567, 20546, 10, 68971]
list_4 = [533878, 651, 658, 8654, 1357, 1254, 9, 68971]
list_5 = [567432, 25732, 3541, 56732, 1567, 20546, 10, 68971]

from bisect import bisect
lists = [list_1, list_2, list_3, list_4, list_5]
srt = list(map(sorted, lists))
from itertools import islice

def get_lcn():
    out = []
    for ind, l in enumerate(lists[:-1]):
        out.append([])
        for ind2, sub in enumerate(islice(srt, ind+1, None), 1):
            for ele in l:
                b = bisect(sub, ele, hi=len(l) - 1)
                if ele > sub[b-1]:
                    continue
                if ele == sub[b-1]:
                    out[-1].append(ele)
                    break
    return out

print(get_lcn())

输出:

[[3541, 25732, 68971, 25732], [3541, 68971, 3541], [68971, 25732], [68971]]

仍然不清楚你真正想要什么,但你可以先构建一个字典,将元素映射到索引:

lists = [list_1, list_2, list_3, list_4, list_5]


from collections import defaultdict

d = defaultdict(lambda: defaultdict(int))

for ind, l in enumerate(lists, 1):
    k = "list_{}".format(ind)
    for ind, ele in enumerate(l):
        d[k][ele] = ind

from itertools import islice
for ind, sub in enumerate(lists, 1):
    k = "list_{}".format(ind)
    for ind2, sub2 in enumerate(islice(lists, ind,None),1):
        for ind3, ele in enumerate(sub2):
            if ele in d[k]:
                print("first common between {} and {} at indexes {}, {} "
                      "and element is {}".format(k, "list_{}".format(ind2+ind), d[k][ele], ind3, ele))
                break
    print(" ")

输出:

first common between list_1 and list_2 at indexes 2, 2 and element is 3541
first common between list_1 and list_3 at indexes 1, 1 and element is 25732
first common between list_1 and list_4 at indexes 7, 7 and element is 68971
first common between list_1 and list_5 at indexes 2, 1 and element is 3541

first common between list_2 and list_3 at indexes 2, 2 and element is 3541
first common between list_2 and list_4 at indexes 7, 7 and element is 68971
first common between list_2 and list_5 at indexes 2, 1 and element is 3541

first common between list_3 and list_4 at indexes 7, 7 and element is 68971
first common between list_3 and list_5 at indexes 2, 1 and element is 3541

first common between list_4 and list_5 at indexes 7, 6 and element is 68971

如果您想在任何地方找到第一个匹配项,那么 zip 将 无效 ,zip 会将同一索引处的元素压缩在一起,并截断任何更长的列表丢失元素。所以你接受的答案是完全错误的,可以通过以下方式进行测试:

 [567432, 3541, 56732, 1567, 20546, 10, 68971,4]

应该 return 索引 6 和 68971 作为列表 4 和 5 之间的公共元素,但 return 什么都没有。

最后的代码对列表进行了两次循环,对每个子列表的元素进行了一次循环,其中包含两次 0(1) 查找