【问题标题】:Find multiple list items within a string在字符串中查找多个列表项
【发布时间】:2014-02-26 17:06:34
【问题描述】:

解决我试图计算字符串中元音数量的问题。我写了以下代码:

def vowel_count(s):
    count = 0
    for i in s:
        if i == 'a' or i == 'e' or i == 'i' or i == 'o' or i == 'u':
            count += 1
    print count
vowel_count(s)

虽然上述方法有效,但我想知道如何通过创建所有元音的列表来更简单地做到这一点,然后通过该列表循环我的 If 语句,而不是进行多个布尔检查。我确信有一种更优雅的方法可以使用导入模块来执行此操作,但对这种类型的解决方案很感兴趣。

相对菜鸟...感谢帮助。

【问题讨论】:

  • 为了学习,如果你想保持你当前的for循环结构,把多个布尔检查改为if i in ('a','e','i','o','u'):
  • @JesseMu if i in ('a', 'e', 'i', 'o', 'u'): 更合适,因为if i in 'aeiou': 也会匹配i == 'eio',这不是代码的意图。
  • @SethMMorton 好点,已编辑

标签: python


【解决方案1】:

无需创建列表,您可以使用'aeiou' 之类的字符串来执行此操作:

>>> vowels = 'aeiou'
>>> s = 'fooBArSpaM'
>>> sum(c.lower() in vowels for c in s)
4

【讨论】:

  • 为了极致的速度和清晰度,我推荐vowels = set('aeiou')。这有两个优点:1)在内部,这变成了{'a', 'e', 'i', 'o', 'u'},这实际上是代码的意图,因为i in 'aeiou' 可以匹配'eou',这不是 OP 想要的,2)set 成员资格很快(这不是一个真正的问题,因为可迭代是 5 个元素,但它可能对更长的字符串很重要)。
【解决方案2】:

您实际上可以像对待 python 中的列表一样对待字符串(因为它们都是可迭代的),例如

vowels = 'aeiou'
sum(1 for i in s if i.lower() in vowels)

为了完整起见,其他人建议vowels = set('aeiou') 允许不匹配的检查,例如'eio' in vowels。但是请注意,如果您在 for loop 中一次一个字符地迭代您的字符串,则不会遇到此问题。

【讨论】:

  • a string as a list 不完全是。字符串和列表都是iterables,这允许它们进行迭代。
  • sum([i.lower() in vowels for i in s]) 也可以工作,因为 True == 1 在 python 中。
  • @SethMMorton 同意更惯用的说法。由于这是在 Ashwini 的帖子中提供的,因此我将按原样离开。
  • 正确的语法是set(['a','e','i','o','u'])set('aeiou'),因为set 必须采用可迭代对象。
  • @SethMMorton 刚刚在您发表评论之前修复。
【解决方案3】:

一个奇怪的解决方法如下:

vowels = len(s) - len(s.translate(None, 'aeiou'))

您对s.translate(None, 'aeiou') 所做的是创建删除所有元音的字符串副本。然后检查长度有何不同。

特别说明:我的使用方式是偶part of the official documentation

什么是元音?

但请注意,此处介绍的方法仅替换 完全 translate 字符串方法的第二个参数中存在的字符。特别是,这意味着它不会替换大写字符,更不用说重音字符(如 áèïôǔ)。

大写元音

解决大写的问题很简单,只需对已转换为小写的字符串的副本进行替换即可:

vowels = len(s) - len(s.lower().translate(None, 'aeiou'))

重读元音

这个有点复杂,但感谢this other SO question,我们知道最好的方法。结果代码将是:

from unicodedate import normalize

# translate special characters to unaccented versions
normalized_str = normalize('NFD', s).encode('ascii', 'ignore')
vowels = len(s) - len(normalized_str.lower().translate(None, 'aeiou'))

【讨论】:

  • -1 strip 只删除尾随和前导字符。 s.translate(None, 'aeiou') 是一个选项。
  • 呃,我的错。我正在检查字符串方法,并打算使用翻译而不是拆分,但我的大脑把它搞砸了。已更正
【解决方案4】:

您可以使用列表推导进行过滤,如下所示:

len([letter for letter in s if letter in 'aeiou'])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    • 2015-02-18
    • 1970-01-01
    • 2022-07-07
    • 1970-01-01
    相关资源
    最近更新 更多