繁体   English   中英

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

[英]First common element from different lists of numbers

我正在尝试从5个单独的号码列表中找到第一个公用号码(FCN)。 例如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但它返回列的生成器而不是列表:

>>> 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]

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

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]]

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

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]

它应返回索引6和68971作为列表4和5之间的公共元素,但不返回任何内容。

最后一个代码在列表上有两个循环,在每个子列表的元素上有一个循环,其中有两个0(1)查找

接下来呢?

我假设有几件事-所有列表的长度相等。 那么在这种情况下-

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处取元组的第一个元素。

这是你想要的吗?

暂无
暂无

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

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