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

时间:2015-06-07 14:21:46

标签: python list python-2.7 tree numbers

我正试图从中找到第一个公共号码(FCN)。 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与列表_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次。

3 个答案:

答案 0 :(得分:2)

您可以使用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.izipzip类似,但它返回列的生成器而不是列表:

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

答案 1 :(得分:2)

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

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]

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

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

答案 2 :(得分:0)

以下怎么样?

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

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

这是你想要的吗?