请注意,您的原始方法实际上是 O(#words 2 ) 时间,因此不适用于可能超过 10000 个单词的大型数据集。
groupby 单线:
我见过的最优雅itertools.groupby
、最奇怪的用例之一:
>>> [list(v) for k,v in groupby(sorted(words,key=sorted),sorted)]
[['cat', 'act'], ['wer', 'erw']]
defaultdict 三线:
使用collections.defaultdict
,您可以执行以下操作:
anagrams = defaultdict(list)
for w in words:
anagrams[tuple(sorted(w))].append(w)
至于如果在没有任何导入的情况下按照您的原始方式进行操作,您可以模拟collections.defaultdict
如下:
anagrams = {}
for w in words:
key = tuple(sorted(w))
anagrams.setdefault(key,[]).append(w)
例子:
>>> anagrams
{('e', 'r', 'w'): ['wer', 'erw'], ('a', 'c', 't'): ['cat', 'act']}
(也写在whi 的回答中。)
地图减少:
这个问题也是 map-reduce 的典型问题,您使用的归约键是排序后的字母(或者更有效的是哈希)。这将允许您大规模并行化问题。
如果我们假设单词的长度是有界的,则groupby
解是O(#words log(#words))
,而哈希解是预期的O(#words)
。在不太可能的情况下,单词的长度是任意的,排序(O(length log(length))
每个单词)比使用与顺序无关的字母散列(每个单词)效率低O(length)
。可悲的是, collections.Counter 不可散列,因此您必须自己编写。