简体   繁体   中英

Python: Indexing a string with specific conditions

I need help with this: Find the number of words that contain none of the five vowels and three y's.

So far, I have:

def no_vowels_yyy(s):
        count = 0
        list_of_vowels = ['a', 'e', 'i', 'o', 'u']
        for i in range(0, len(s)):
                if s[i] not in list_of_vowels and (s[i] == 'y') == 3:
                        return True
        return False

This is not working though...

Your check for the number of y's (s[i] == 'y') == 3: is what's causing it not to work. Comparing s[i] to 'y' will give you a boolean (true/false) result, not the number of matches. Since you are looping through, you could just keep a count of the number of y's you've found.

def no_vowels_yyy(s):
    count = 0
    list_of_vowels = ['a', 'e', 'i', 'o', 'u']
    for i in range(0, len(s)):
            if s[i] in list_of_vowels:
                return False
            if s[i] == 'y':
                count += 1

    return count == 3

Since others have already told you what's the problem, I'll just offer a solution of my own. This is probably the best way, I can't see why not to use string.count() -method:

def no_vowels_yyy(s):
    if any(c in {'a', 'e', 'i', 'o', 'u'} for c in s):
        return False
    return s.count('y') == 3

Here is a slightly different solution.

First, we build a set of vowels. It is very fast to check if a particular character is in this set, or not; faster than checking in a list. Also, we build it once, outside the function, instead of building it every time the function is called.

We use any() with a generator expression that checks each character to see if it is in the set. If any character is in the set of vowels, we return False.

Next, we use sum() with a generator expression to count how many 'y' characters there are; for each character that is a 'y' , the value 1 is added by the sum() function. We return whether this result is 3.

This will be a bit faster than looping over the string with an index and updating a counter variable. This is more of a "Pythonic" solution. On the other hand, this loops over the string twice rather than once.

_vowels = set(['a', 'e', 'i', 'o', 'u'])

def no_vowels_yyy(s):
    if any(ch in _vowels for ch in s):
        return False

    return s.count('y') == 3

print(no_vowels_yyy("zyzyxy"))

Just to show another way...:

from collections import Counter
def func(text):
    freq = Counter(text)
    return freq['y'] == 3 and not (freq.viewkeys() & 'aeiou')

Has the advantage of just one parse, but doesn't short circuit on vowels...

Otherwise, to short circuit as soon as possible:

y_count = 0
for ch in word:
    if ch in {'a', 'e', 'i', 'o', 'u'}:
        return False
    elif ch == 'Y':
        y_count += 1
        if y_count > 3:
            return False
return y_count == 3
def no_vowels_yyy(s, _vowels=set("aeiou")):
    return s.count("y") == 3 and _vowels.isdisjoint(s)
print(no_vowels_yyy("zyzyxy")) # -> True

Or a more readable version:

def no_vowels_yyy(s):
    return s.count("y") == 3 and all(c not in "aeiou" for c in s)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM