【问题标题】:list of lists of anagram in pythonpython中的字谜列表列表
【发布时间】: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']]

此外,我不想使用任何导入(字符串除外)。什么错误?

【问题讨论】:

    标签: python python-2.7 anagram


    【解决方案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。)


    ma​​p-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
      猜你喜欢
      • 2019-01-17
      • 2015-07-26
      • 2015-05-11
      • 2020-09-20
      • 2012-06-21
      • 2020-02-21
      • 2011-09-19
      • 2014-04-03
      • 2022-01-18
      相关资源
      最近更新 更多