Python: 不冗余的列表项之间的比较
Python: Comparison between list items that isn't redundant
假设我有一个列表嵌套在字典的键中。所以像这样:
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 循环可能会变得多余,因为它会重复进行两次相同的比较。有什么办法可以使比较没有冗余吗?
您可以使用 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
函数有效,这应该会产生您想要的行为。
如果你想将列表中的人相互比较,这样我就可以制作一个连接以相同首字母开头的名字的图表。然后使用字典并在 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
.
的值即可将其添加到图表中
如果您想在长度大于 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 我们可以看到,因为我们的线性传递创建了一个分组字典,所以我们可以简单地遍历输出字典中的每个值列表并创建唯一配对:
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')
假设我有一个列表嵌套在字典的键中。所以像这样:
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 循环可能会变得多余,因为它会重复进行两次相同的比较。有什么办法可以使比较没有冗余吗?
您可以使用 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
函数有效,这应该会产生您想要的行为。
如果你想将列表中的人相互比较,这样我就可以制作一个连接以相同首字母开头的名字的图表。然后使用字典并在 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
.
如果您想在长度大于 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 我们可以看到,因为我们的线性传递创建了一个分组字典,所以我们可以简单地遍历输出字典中的每个值列表并创建唯一配对:
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')