【问题标题】:Delete words which have 2 consecutive vowels in it删除其中有 2 个连续元音的单词
【发布时间】:2015-02-05 23:38:21
【问题描述】:

我想要的是删除其中包含两个以上连续元音的单词。所以输入:

s = " There was a boat in the rain near the shore, by some mysterious lake"

输出:

[boat,rain,near,mysterious] 

这是我的代码。 我只是想知道是否有更好的方法可以做到这一点,或者这是否足够有效。如果你可以用 python dict 或列表来做到这一点,可以吗? :) 我是 python 新手,所以是的。 :) cmets 会很好。

def change(s):
vowel = ["a","e","i","o","u"]
words = []
a = s[:].replace(",","").split()
for i in vowel:
    s = s.replace(i, "*").replace(",","")
for i,j in enumerate(s.split()):
    if "**" in j:
        words.append(a[i])
return words

【问题讨论】:

  • "有两个以上连续元音的单词" 你的意思是有两个或更多个连续元音的单词?否则只有mysterious 计数。
  • 出于好奇,当前的解决方案将 ajcr 的胜利(时间)公布了几微秒。 re.search 进入 ~21micros,设置交叉切片进入 ~60micros。成对迭代大约 35 微秒。

标签: python performance algorithm


【解决方案1】:

或者,您始终可以使用正则表达式和列表推导来获取单词列表:

>>> import re
>>> [x for x in s.split() if re.search(r'[aeiou]{2}', x)]
['boat', 'rain', 'near', 'mysterious']

s.split() 将句子拆分为单词列表。表达式[x for x in s.split()] 依次考虑此列表中的每个单词。

表达式的re.search(r'[aeiou]{2}', x) 部分在每个单词中搜索来自[aeiou] 组的两个连续字母。只有找到两个连续的元音,才会将单词放入新列表中。

【讨论】:

  • 不要忘记模式中的逗号,否则这将严格搜索两个连续的元音,而不是至少搜索。
  • @MalikBrahimi {2,} 严格来说是{2} 的超集。您不需要结尾的逗号。
【解决方案2】:

使用集合:

使用set.intersection 的第一种方法只会找到不完全相同的连续对,因此oo 不会匹配:

s = " There was a boat in the rain near the shore, by some mysterious lake"
vowels = "aeiouAEIOU"
print([x for x in s.split() if any(len(set(x[i:i+2]).intersection(vowels))==  2 for i in range(len(x))) ])
['boat', 'rain', 'near', 'mysterious']

方法 2 使用set.issubset,因此现在相同的连续对将被视为匹配。

set.issubset 与使用yield from python 3 语法的函数一起使用,这可能更合适,并且确实可以捕获重复的相同元音:

vowels = "aeiouAEIOU"
def get(x, step):
    yield from (x[i:i+step] for i in range(len(x[:-1])))

print([x for x in s.split() if any(set(pr).issubset(vowels) for pr in get(x, 2))])

或再次在单个列表组合中:

print([x for x in s.split() if any(set(pr).issubset(vowels) for pr in (x[i:i+2] for i in range(len(x[:-1]))))])

最后将元音设为一个集合并检查它是否是任何一对字符的set.issuperset

vowels = {'a', 'u', 'U', 'o', 'e', 'i', 'A', 'I', 'E', 'O'}


def get(x, step):
    yield from (x[i:i+step] for i in range(len(x[:-1])))

print([x for x in s.split() if any(vowels.issuperset(pr) for pr in get(x, 2))])

【讨论】:

  • 使用切片设置交集是看待这个问题的一种新方法。我喜欢!
  • 这是您最后一个示例的变体,不需要辅助函数:[x for x in s.split() if any(vowels.issuperset(pr) for pr in zip(x, x[1:]))]
【解决方案3】:

使用成对迭代:

from itertools import tee

def pairwise(iterable):
    a, b = tee(iter(iterable))
    next(b)
    return zip(a,b)

vowels = 'aeiouAEIOU'
[word for word in s.split() if any(
        this in vowels and next in vowels for this,next in pairwise(word))]

【讨论】:

    【解决方案4】:

    改用正则表达式:

    import re
    
    s = 'There was a boat in the rain near the shore, by some mysterious lake'
    l = [i for i in s.split(' ') if re.search('[aeiou]{2,}', i)]
    
    print ' '.join(l) # back to string
    

    【讨论】:

    • 这里有几个大问题。你正在改变你正在迭代的同一个列表:for word in l: ... l.remove(word) 很可怕,使用for word in l[:];和if not ... is None——只需使用if re.search(r'[aeiou]{2}', word)。另请注意,您不需要该量词中的尾随逗号,因为您只关心连续两个,而不关心是否还有更多。
    • 在问题中它说得更多。其次,迭代很好,因为我不是按索引进行迭代,而是使用 foreach 进行迭代。
    • 正如我在另一个答案中提到的,不可能匹配 {2} 而不是 {2,}。您的正则表达式在匹配 2 时应该退出,没有理由继续匹配更多。我考虑改变你正在迭代代码气味的列表。仅仅因为它没有破坏这个用例并不意味着它是好的代码。
    【解决方案5】:

    使用产品代替:

    from itertools import product
    
    vowels = 'aiueo'
    comb = list(product(vowels, repeat=2))
    s = " There was a boat in the rain near the shore, by some mysterious lake"
    
    
    def is2consecutive_vowels(word):
        for i in range(len(word)-1):
            if (word[i], word[i+1]) in comb:
                return True
        return False
    
    print [word for word in s.split() if is2consecutive_vowels(word)]
    # ['boat', 'rain', 'near', 'mysterious']
    

    或者如果您不需要使用任何外部库:

    vowels = 'aeiou'
    
    def is2consecutive_vowels2(word):
        for i in range(len(word)-1):
            if word[i] in vowels and word[i+1] in vowels:
                return True
        return False
    
    print [word for word in s.split() if is2consecutive_vowels2(word)]
    # ['boat', 'rain', 'near', 'mysterious']
    

    这个比正则表达式解决方案还要快!

    【讨论】:

      【解决方案6】:
      a=[]
      def count(s):
          c=0
          t=s.split()
          for i in t:
              for j in range(len(i)-1):
                  w=i[j]
                  u=i[j+1]
                  if u in "aeiou" and w in "aeiou":
                      c+=1
              if(c>=1):
                  a.append(i)
              c=0
          return(a)
      print(count("There was a boat in the rain near the shore, by some mysterious lake"))
      

      【讨论】:

        猜你喜欢
        • 2015-06-22
        • 2020-08-17
        • 2013-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多