python中的字谜列表列表
Posted
技术标签:
【中文标题】python中的字谜列表列表【英文标题】:list of lists of anagram in python 【发布时间】:2012-06-07 07:19:09 【问题描述】:如果我的输入是这样的列表:
words = ['cat','act','wer','erw']
我想制作一个这样的字谜列表 -
[['cat','act'],['wer','erw']]
我尝试过这样做:
[[w1 for w in words if w!=w1 and sorted(w1)==sorted(w)] for w1 in words]
但它不起作用。输出是:
[['cat'], ['act'], ['wer'], ['erw']]
此外,我不想使用任何导入(字符串除外)。什么错误?
【问题讨论】:
【参考方案1】:请注意,您的原始方法实际上是 O(#words2) 时间,因此不适用于可能超过 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's answer。)
map-reduce:
这个问题也是 map-reduce 的典型问题,您使用的归约键是排序后的字母(或者更有效的是哈希)。这将使您能够大规模并行化问题。
如果我们假设单词的长度是有界的,那么groupby
的解是O(#words log(#words))
,而哈希解是O(#words)
。在不太可能的情况下,单词的长度是任意的,排序(O(length log(length))
每个单词)比使用与顺序无关的字母散列(O(length)
每个单词)效率低。遗憾的是,collections.Counter 不可散列,因此您必须自己编写。
【讨论】:
优雅简洁,可惜OP说没有使用任何import @NickCraig-Wood:啊,错过了;不过,我想我会把它留在这里以供将来参考。 是的,把它留在这里 - 这是一个很好的解决方案!【参考方案2】:words = ['cat','act','wer','erw']
dic=
for w in words:
k=''.join(sorted(w))
dic.setdefault(k,[])
dic[k].append(w)
print dic.values()
性能更好:O(n)
【讨论】:
写dic.setdefault(k,[]).append(w)
的效率稍微高一些 - 省去了在字典中查找键两次【参考方案3】:
您可以通过谷歌搜索一次找到单个单词的字谜的各种解决方案。与明显的“搜索我知道的所有单词并查看它们是否具有相同的字母”相比,可能会有一个更有效的求解器。
一旦有了,就可以将其放入函数中:
def anagrams(word):
"return a list of all known anagrams of *word*"
一旦你有了它,将它概括为一个单词列表是微不足道的:
[anagrams(word) for word in words]
【讨论】:
【参考方案4】:这个应该是你喜欢的风格
[[w, w1] for w1 in words for w in words if w!=w1 and sorted(w1)==sorted(w)][::2]
【讨论】:
这是 O(len(words)**2) 所以如果有很多单词这会很慢。您已将for w1 in words
嵌套在 for w in words
中。
@NickCraig-Wood 你是对的,这不是一个快速的解决方案,但它是“pythonic”:)
以及 [::2] 在你的 solotion 中是什么意思
@EyalDreifuss [::2] 表示从第一个元素开始,每隔一个元素取一个
@EyalDreifuss 为您解答,这部分[w1 for w in words if w!=w1 and sorted(w1)==sorted(w)]
仅获取每个元素并将它们中的每一个元素设为列表;即使在这种情况下,开头也应该是w
而不是w1
,否则你只是从外部循环中获取w1
以上是关于python中的字谜列表列表的主要内容,如果未能解决你的问题,请参考以下文章