元の方法は実際には O(#words 2 ) 時間であるため、おそらく 10000 語を超える大規模なデータセットでは機能しないことに注意してください。
groupby ワンライナー:
私が今まで見た中で最もエレガントitertools.groupby
で奇妙な使用例の 1 つ:
>>> [list(v) for k,v in groupby(sorted(words,key=sorted),sorted)]
[['cat', 'act'], ['wer', 'erw']]
defaultdict 3ライナー:
を使用する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 はハッシュ可能ではないため、独自に作成する必要があります。