【发布时间】:2018-01-30 06:59:33
【问题描述】:
我正在处理一大堆具有多对多相关性的元组,我想制作一个字典,其中 (a,b) 的每个 b 都有一个与 a b 对应的所有 a 的列表.在字典中的键 b 处测试一个列表似乎很尴尬,然后查找一个 a,如果它不存在则附加 a,每次都通过元组消化循环;但我还没有找到更好的方法。一个存在吗?还有其他更漂亮的方法吗?
【问题讨论】:
-
更漂亮是指语法还是算法?
我正在处理一大堆具有多对多相关性的元组,我想制作一个字典,其中 (a,b) 的每个 b 都有一个与 a b 对应的所有 a 的列表.在字典中的键 b 处测试一个列表似乎很尴尬,然后查找一个 a,如果它不存在则附加 a,每次都通过元组消化循环;但我还没有找到更好的方法。一个存在吗?还有其他更漂亮的方法吗?
【问题讨论】:
请参阅the docs 了解setdefault() 方法:
setdefault(key[, default])
如果键是 在字典中,返回它的值。 如果不是,则插入值为 默认并返回默认值。默认 默认为无。
您可以将其用作单个调用,如果 b 存在则获取 b,或者如果 b 不存在则将 b 设置为空列表 - 无论哪种方式,都返回 b:
>>> key = 'b'
>>> val = 'a'
>>> print d
{}
>>> d.setdefault(key, []).append(val)
>>> print d
{'b': ['a']}
>>> d.setdefault(key, []).append('zee')
>>> print d
{'b': ['a', 'zee']}
将此与一个简单的“不在”检查结合起来,您已经在三行中完成了您所追求的:
>>> b = d.setdefault('b', [])
>>> if val not in b:
... b.append(val)
...
>>> print d
{'b': ['a', 'zee', 'c']}
【讨论】:
defaultdict 比setdefault 好一点,前提是你有 Python 2.5 或更高版本。
set() 很好,但直到 2.4 才内置。为什么你的 Python 这么老? :-(
defaultdict 还需要额外导入 collections
假设您并没有真正受制于列表,defaultdict 和 set 非常方便。
import collections
d = collections.defaultdict(set)
for a, b in mappings:
d[b].add(a)
如果你真的想要列表而不是集合,你可以在后面加上一个
for k, v in d.iteritems():
d[k] = list(v)
如果你真的想要一个dict而不是defaultdict,你可以说
d = dict(d)
不过,我真的看不出有什么理由。
【讨论】:
defaultdict,因为它确实是最 Pythonic 的解决方案。
使用 collections.defaultdict
your_dict = defaultdict(list)
for (a,b) in your_list:
your_dict[b].append(a)
【讨论】:
set 而不是 list 的原因。
defaultict(list) 是对的。如果“它”表示集合中的每个项目,那么defaultdict(set) 是正确的。而当“它”下雨时,“它”与什么有关?
set 可能比list 更有意义。
你可以排序你的元组 O(n log n) 然后创建你的字典 O(n)
或者更简单的 O(n),但是在有很多元组的情况下可能会给内存带来沉重的负担:
your_dict = {}
for (a,b) in your_list:
if b in your_dict:
your_dict[b].append(a)
else:
your_dict[b]=[a]
嗯,和你描述的差不多。这有什么尴尬的?
您也可以考虑使用 sql 数据库来完成这项繁琐的工作。
【讨论】:
而不是使用if,AFAIK 更pythonic 使用try 块代替。
your_list=[('a',1),('a',3),('b',1),('f',1),('a',2),('z',1)]
your_dict={}
for (a,b) in your_list:
try:
your_dict[b].append(a)
except KeyError:
your_dict[b]=[a]
print your_dict
【讨论】:
我不确定你将如何摆脱键测试,但是一旦它们的键/值对被初始化就很容易了:)
d = {}
if 'b' not in d:
d['b'] = set()
d['b'].add('a')
该集合将确保集合中只有 1 个“a”。您需要进行初始的“b”检查以确保键/值存在。
【讨论】:
字典get 方法?
如果some_key 在字典中,则返回my_dict[some_key] 的值,否则返回一些默认值(以下示例中的[]):
my_dict[some_key] = my_dict.get(some_key, []).append(something_else)
【讨论】:
append 不返回列表。它变成my_dict[some_key] = None。
还有另一种相当有效(尽管可能不如集合有效)且简单的方法。它在实践中类似于defaultdict,但不需要额外的导入。
假设您有一个带有空(无)键的 dict,这意味着您还在某处创建了 dict 键。您可以使用dict.fromkeys 方法来做到这一点,并且此方法还允许为所有键设置默认值。
keylist = ['key1', 'key2']
result = dict.fromkeys(keylist, [])
result 将是:
{'key1':[],'key2':[]}
然后你可以做你的循环并直接使用result['key1'].append(..)
【讨论】: