Python 用听写理解附加到列表的听写上
假设我有一大堆单词。例如:Python 用听写理解附加到列表的听写上,python,dictionary,Python,Dictionary,假设我有一大堆单词。例如: >>> with open('/usr/share/dict/words') as f: ... words=[word for word in f.read().split('\n') if word] 如果我想根据单词列表的第一个字母建立索引,这很简单: d={} for word in words: if word[0].lower() in 'aeiou': d.setdefault(word[0].lower(
>>> with open('/usr/share/dict/words') as f:
... words=[word for word in f.read().split('\n') if word]
如果我想根据单词列表的第一个字母建立索引,这很简单:
d={}
for word in words:
if word[0].lower() in 'aeiou':
d.setdefault(word[0].lower(),[]).append(word)
# You could use defaultdict here too...
结果如下:
{'a':[list of 'a' words], 'e':[list of 'e' words], 'i': etc...}
有没有一种方法可以通过Python 2.7、3+dict理解来实现这一点?换句话说,在构建dict时,dict理解语法是否可以附加由键表示的列表
即:
其中XXX在创建索引时对键执行追加操作或列表创建
编辑
采纳建议和基准:
def f1():
d={}
for word in words:
c=word[0].lower()
if c in 'aeiou':
d.setdefault(c,[]).append(word)
def f2():
d={}
{d.setdefault(word[0].lower(),[]).append(word) for word in words
if word[0].lower() in 'aeiou'}
def f3():
d=defaultdict(list)
{d[word[0].lower()].append(word) for word in words
if word[0].lower() in 'aeiou'}
def f4():
d=functools.reduce(lambda d, w: d.setdefault(w[0], []).append(w[1]) or d,
((w[0].lower(), w) for w in words
if w[0].lower() in 'aeiou'), {})
def f5():
d=defaultdict(list)
for word in words:
c=word[0].lower()
if c in 'aeiou':
d[c].append(word)
生成此基准:
rate/sec f4 f2 f1 f3 f5
f4 11 -- -21.8% -31.1% -31.2% -41.2%
f2 14 27.8% -- -11.9% -12.1% -24.8%
f1 16 45.1% 13.5% -- -0.2% -14.7%
f3 16 45.4% 13.8% 0.2% -- -14.5%
f5 18 70.0% 33.0% 17.2% 16.9% --
带默认dict的直接循环最快,其次是set CONTRUMENT和带setdefault
的循环
谢谢你的想法 无dict理解设计用于在每次迭代中生成非重叠键;它们不支持聚合。对于这个特定的用例,循环是有效完成任务(在线性时间内)的正确方法。我将使用过滤器
:
>>> words = ['abcd', 'abdef', 'eft', 'egg', 'uck', 'ice']
>>> index = {k.lower() : list(filter(lambda x:x[0].lower() == k.lower(),words)) for k in 'aeiou'}
>>> index
{'a': ['abcd', 'abdef'], 'i': ['ice'], 'e': ['eft', 'egg'], 'u': ['uck'], 'o': []}
听写理解是不可能的(至少是容易或直接的)
这是可能的,但可能滥用语法,具有集合或列表理解:
# your code:
d={}
for word in words:
if word[0].lower() in 'aeiou':
d.setdefault(word[0].lower(),[]).append(word)
# a side effect set comprehension:
index={}
r={index.setdefault(word[0].lower(),[]).append(word) for word in words
if word[0].lower() in 'aeiou'}
print r
print [(k, len(d[k])) for k in sorted(d.keys())]
print [(k, len(index[k])) for k in sorted(index.keys())]
印刷品:
set([None])
[('a', 17094), ('e', 8734), ('i', 8797), ('o', 7847), ('u', 16385)]
[('a', 17094), ('e', 8734), ('i', 8797), ('o', 7847), ('u', 16385)]
集合理解在遍历words
列表后,生成一个集合,其中包含setdefault()
方法的结果。在这种情况下,集合([None])
的总和。它也会产生你想要的副作用,产生你的清单
它的可读性(IMHO)不如直循环结构,应该避免(IMHO)。它并不更短,也可能不会更快。这是关于Python的有趣的琐事,而不是有用的--IMHO。。。也许是为了赢一个赌注 这不完全是一种听写理解,但:
reduce(lambda d, w: d.setdefault(w[0], []).append(w[1]) or d,
((w[0].lower(), w) for w in words
if w[0].lower() in 'aeiou'), {})
如果words
是一个迭代器,这将中断。但是OP正在获取一个单词列表,这是一个iterable
。当然-但是这种方法还有其他缺点(例如,运行所需时间增加了五倍-取决于输入的大小,常数因子有时是显而易见的。它的可读性也不如只使用for
循环。我同意,for循环在可读性方面总是很好的。是的,这种方法也有点昂贵O(len('aeiou')*len(words))
。除非你在玩代码高尔夫,否则为了简洁起见,请不要写不可读的代码。{w[0]:[ww for ww in words如果ww.startswith(w[0])]for w in words}
@astynax:聪明,但确实很慢设置默认值
当然更好,但这是口述理解:)减少(lambda d,w:d.setdefault(w[0]).append(w)或者d,单词,{})
,但这不是一个dict理解:)谢谢你告诉我为什么我不应该这样做!
reduce(lambda d, w: d.setdefault(w[0], []).append(w[1]) or d,
((w[0].lower(), w) for w in words
if w[0].lower() in 'aeiou'), {})