【问题标题】:How to go from list of words to a list of distinct letters in Python如何从单词列表到 Python 中不同字母的列表
【发布时间】:2011-01-15 19:08:33
【问题描述】:

使用 Python,我试图将一个单词的句子转换为该句子中所有不同字母的平面列表。

这是我当前的代码:

words = 'She sells seashells by the seashore'

ltr = []

# Convert the string that is "words" to a list of its component words
word_list = [x.strip().lower() for x in words.split(' ')]

# Now convert the list of component words to a distinct list of
# all letters encountered.
for word in word_list:
    for c in word:
        if c not in ltr:
            ltr.append(c)

print ltr

这段代码返回['s', 'h', 'e', 'l', 'a', 'b', 'y', 't', 'o', 'r'],这是正确的,但有没有更Pythonic的方式来回答这个问题,可能使用列表推导/set

当我尝试将列表理解嵌套和过滤结合起来时,我得到的是列表列表而不是平面列表。

最终列表(ltr)中不同字母的顺序并不重要;关键是它们是独一无二的。

【问题讨论】:

  • +1 表示一个措辞恰当的问题并包含您的尝试(多么受欢迎的景象!)
  • 请注意,str.split 默认在空格上分割,所以.split(' ') 通常拼写为.split()

标签: python filter distinct list-comprehension letters


【解决方案1】:
words = 'She sells seashells by the seashore'

ltr = list(set(list(words.lower())))
ltr.remove(' ')
print ltr

【讨论】:

【解决方案2】:

这里有一些用 py3k 做的计时:

>>> import timeit
>>> def t():                    # mine (see history)
    a = {i.lower() for i in words}
    a.discard(' ')
    return a

>>> timeit.timeit(t)
7.993071812372081
>>> def b():                    # danben
    return set(letter.lower() for letter in words if letter != ' ')

>>> timeit.timeit(b)
9.982847967921138
>>> def c():                    # ephemient in comment
    return {i.lower() for i in words if i != ' '}

>>> timeit.timeit(c)
8.241267610375516
>>> def d():                    #Mike Graham
    a = set(words.lower())
    a.discard(' ')
    return a

>>> timeit.timeit(d)
2.7693045186082372

【讨论】:

  • @ephemient:它可以工作,但速度有点慢。顺便说一句,set(i.lower for i in words if i != ' ') 版本在 py3k 中慢了 20%
【解决方案3】:
>>> set('她在海边卖贝壳'.replace(' ', '').lower()) 设置(['a','b','e','h','l','o','s','r','t','y']) >>> set(c.lower() for c in '她在海边卖贝壳' if not c.isspace()) 设置(['a','b','e','h','l','o','s','r','t','y']) >>> 从 itertools 导入链 >>> set(chain(*'她在海边卖贝壳'.lower().split())) 设置(['a','b','e','h','l','o','s','r','t','y'])

【讨论】:

    【解决方案4】:

    集合提供了一种简单、高效的解决方案。

    words = 'She sells seashells by the seashore'
    
    unique_letters = set(words.lower())
    unique_letters.discard(' ') # If there was a space, remove it.
    

    【讨论】:

    • 与 ehemient 几乎相同,但如果格式更好,您的答案。
    • @tgray - 这也是最先发布的; ehemient 之后编辑了他的(见编辑日志)。
    • @tgray:这不是关于格式化,而是关于有效地应用.lower
    • @job:为什么?这个解决方案更简洁,即使它是 2 行 并且 它不会对每个字母进行比较。
    • 我在编辑答案时没有注意到这一点,但无论如何,迈克的答案更清晰。 +1
    【解决方案5】:
    set([letter.lower() for letter in words if letter != ' '])
    

    编辑:我刚试了一下,发现这也可以(也许这就是 SilentGhost 所指的):

    set(letter.lower() for letter in words if letter != ' ')
    

    如果你需要一个列表而不是一组,你可以

    list(set(letter.lower() for letter in words if letter != ' '))
    

    【讨论】:

    • 你没有在那里列出理解
    • @Art Metzer:请注意,拆分并不是真正必要的,因为字符串是可迭代的类型。这可能就是您在不想要列表时得到列表的原因。
    • @SilentGhost:我不明白你的评论,你能澄清一下吗?
    • @danben:您可以使用生成器表达式来避免创建新列表。就像伊格纳西奥的回答一样。
    • 您正在使用列表理解,您不必这样做。
    【解决方案6】:
    set(l for w in word_list for l in w)
    

    【讨论】:

    • @danben:你确实注意到word_list已经被空格分割了,对吧?
    【解决方案7】:

    ltr 设为一组并稍微更改循环体:

    ltr = set()
    
    for word in word_list:
        for c in word:
           ltr.add(c)
    

    或者使用列表推导:

    ltr = set([c for word in word_list for c in word])
    

    【讨论】:

      猜你喜欢
      • 2020-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 2020-05-25
      • 1970-01-01
      • 1970-01-01
      • 2021-11-01
      相关资源
      最近更新 更多