Python:用多重列表推导式创建字典

1 投票
4 回答
1223 浏览
提问于 2025-04-17 17:57

有没有办法可以用这个讨论中提到的列表推导来创建字典呢?

listA = [
    "apple_v001",
    "apple_v002",
    "banana_v001",
    "orange_v001",
]
keywords = ["apple", "banana", "orange"]
[[item for item in listA if kw in item] for kw in keywords]
# Result: [['apple_v001', 'apple_v002'], ['banana_v001'], ['orange_v001']] # 

我想做的是用一些关键词作为键,从这个结果中创建一个字典。所以

dictA["apple"] = ['apple_v001', 'apple_v002']

等等。我试过用 dict = {key, value for ...(迭代)} 这样的方式,但总是出现语法错误。我真的不知道该怎么开始,任何帮助都很感激。

4 个回答

1

在评论中你提到你使用的是Python 2.6

。Python 2.6里没有字典推导式,你可以用 dict() 和生成器表达式来代替:

d = dict((kw, [item for item in listA if kw in item]) for kw in keywords)

这里有一个可能更高效的版本:

import re
from collections import defaultdict

search_word = re.compile("(%s)" % "|".join(map(re.escape, keywords))).search

d = defaultdict(list)
for item in listA:
    m = search_word(item)
    if m:
       d[m.group(1)].append(item)

如果 listA 始终是问题中给出的格式:

from collections import defaultdict

keywords = set(keywords)
d = defaultdict(list)
for item in listA:
    word = item.partition("_")[0]
    if word in keywords:
       d[word].append(item)

如果 listA 不包含不在 keywords 中的项目:

from collections import defaultdict

d = defaultdict(list)
for item in listA:
    d[item.partition('_')[0]].append(item)
2
{kw: [item for item in listA if kw in item] for kw in keywords}
>>> from itertools import groupby
>>> {k:list(g) for k,g in groupby(sorted(listA), key=lambda x:x.partition('_')[0])}
{'orange': ['orange_v001'], 'apple': ['apple_v001', 'apple_v002'], 'banana': ['banana_v001']}
dict((kw, [item for item in listA if kw in item]) for kw in keywords)
>>> from itertools import groupby
>>> dict((k,list(g)) for k,g in groupby(sorted(listA), key=lambda x:x.partition('_')[0]))
{'orange': ['orange_v001'], 'apple': ['apple_v001', 'apple_v002'], 'banana': ['banana_v001']}

不过,这似乎不是创建这样的字典特别有效的方法。

举个例子,这种方法不需要提前知道关键词的列表,而且效率还算不错。

对于Python2.6来说,类似的写法是

2

如果你不想用一行代码解决问题,可以看看这个。

In [58]: d
Out[58]: defaultdict(<type 'list'>, {})

In [59]: for elem in keywords:
   ....:     for item in listA:
   ....:         if item.startswith(elem):
   ....:             d[elem].append(item)
   ....:

In [60]: d
Out[60]: defaultdict(<type 'list'>, {'orange': ['orange_v001'], 'apple': ['apple_v001', 'apple_v002'], 'banana': ['banana_v001']})

撰写回答