假设我有一个嵌套在dict键中的列表。所以像这样:
d = {'people':['John', 'Carry', 'Joe', 'Greg', 'Carl', 'Gene']}
我想比较列表中的人员,以便我可以创建一个图表,连接以相同的第一个字母开头的名称。
我想出了一个嵌套的for循环来尝试解决这个问题:
for subject in d.keys():
for word1 in d[people]:
for word2 in d[people]:
if word1[0] == word2[0]:
g.connectThem(word1,word2)
但嵌套的for循环可能会变得多余,因为它会使两次相同的比较。有没有办法让它在比较方面没有冗余?
答案 0 :(得分:2)
您可以使用itertools.combinations
for pair in itertools.combinations(d['people'], 2):
first, second = pair
if first[0] == second[0]:
g.connectThem(first, second)
这些是从combinations
[('John', 'Carry'), ('John', 'Joe'), ('John', 'Greg'), ('John', 'Carl'), ('John', 'Gene'),
('Carry', 'Joe'), ('Carry', 'Greg'), ('Carry', 'Carl'), ('Carry', 'Gene'),
('Joe', 'Greg'), ('Joe', 'Carl'), ('Joe', 'Gene'),
('Greg', 'Carl'), ('Greg', 'Gene'),
('Carl', 'Gene')]
请注意,您没有重复的问题(通过颠倒对的顺序)
假设您的connectThem
函数有效,这应该会产生您想要的行为。
答案 1 :(得分:1)
如果你想将列表中的人物相互比较,以便我可以创建一个图表,连接以相同的第一个字母开头的名称。然后使用dict和单个传递d["people"]
您使用名字的第一个字母作为键,因此解决方案为0(n)
,并且明显比二次方更有效,因为所有组合都会产生大多数不必要的配对:
d = {"people":['John', 'Carry', 'Joe', 'Greg', 'Carl', 'Gene']}
from collections import defaultdict
my_d = defaultdict(list)
for v in d["people"]:
my_d[v[0]].append(v)
print(my_d)
defaultdict(<type 'list'>, {'C': ['Carry', 'Carl'], 'J': ['John', 'Joe'], 'G': ['Greg', 'Gene']})
现在,您可以通过迭代my_d
的值,将具有常用名字的完整名称列表传递给要添加到图表的方法。
如果要创建列表长度为&gt;的人员组合。 2然后你可以使用原始列表保存多个不必要的组合。它只会结合你想要的实际名称。
因此,要处理重复的名称,只能使用具有共同首字母的名称进行组合,并且只考虑具有链接的组,即具有非唯一首字母的名称:
from collections import defaultdict
# store all names in groups, grouped by common first letter in names
my_d = defaultdict(set)
for v in d["people"]:
# 0(1) set lookup avoids adding names twice
if v not in my_d[v[0]]:
my_d[v[0]].add(v)
from itertools import combinations
for group in my_d.itervalues():
# two elements are a combination
if len(group) == 2:
g.connectThem(group[0],group[1])
# ignore uniques names ?
elif len(group) > 2:
for n1,n2 in combinations(group,2):
g.connectThem(n1 ,n2)
根本没有使用itertools我们可以看到,因为我们的线性传递创建了一个分组的dict,我们可以简单地遍历out dict中的每个值列表并创建唯一的配对:
for group in my_d.itervalues():
for ind, n1 in enumerate(group):
for n2 in group[ind+1:]:
print(n1,n2)
('Carry', 'Carl')
('John', 'Joe')
('Greg', 'Gene')