我正试图从中找到第一个公共号码(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次。
答案 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.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]
答案 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处取元组的第一个元素。
这是你想要的吗?