创建列表的有效方法,或者如果已存在则附加到列表?

use*_*228 40 python list

我正在浏览一大堆具有多对多关系的元组,我想创建一个字典,其中(a,b)的每个b都有一个与b对应的所有a的列表.在字典中的键b处测试列表似乎很尴尬,然后查找a,然后在每次通过元组摘要循环时追加a(如果它不存在); 但我还没有找到更好的方法.有人存在吗?有没有其他方法可以做到这一点更漂亮?

Jam*_*ley 58

请参阅该方法的文档setdefault():

setdefault(key [,default])
如果key在字典中,则返回其值.如果不是,请插入值为default的值并返回default.默认默认为无.

您可以将其用作单个调用,如果它存在则将获得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']}
Run Code Online (Sandbox Code Playgroud)

将它与一个简单的"不在"检查相结合,你已经完成了三行中的所有工作:

>>> b = d.setdefault('b', [])
>>> if val not in b:
...   b.append(val)
... 
>>> print d
{'b': ['a', 'zee', 'c']}
Run Code Online (Sandbox Code Playgroud)

  • 假设你有Python 2.5或更高版本,`defaultdict`比`setdefault`好一点. (5认同)
  • D'哦.`set()`很好但直到2.4才开始内置.为什么你的Python太老了?:-( (5认同)

eph*_*ent 17

假设你并没有真正依赖于列表,那么defaultdictset非常方便.

import collections
d = collections.defaultdict(set)
for a, b in mappings:
    d[b].add(a)
Run Code Online (Sandbox Code Playgroud)

如果你真的想要列表而不是集合,你可以用一个

for k, v in d.iteritems():
    d[k] = list(v)
Run Code Online (Sandbox Code Playgroud)

如果你真的想要一个dict而不是一个默认的dict,你可以说

d = dict(d)
Run Code Online (Sandbox Code Playgroud)

不过,我真的没有看到你想要的任何理由.

  • +1 为 `defaultdict`,因为它确实是最 Pythonic 的解决方案。 (2认同)

S.L*_*ott 5

使用 collections.defaultdict

your_dict = defaultdict(list)
for (a,b) in your_list:
    your_dict[b].append(a)
Run Code Online (Sandbox Code Playgroud)