1

Is it possible to reduce the amount of lines in the method find_indexes to just 1 line using an if/else statement like as seen in the return statement?

def find_indexes(sentence, target):
    indexes = [index for index, x in enumerate(sentence.split()) if target == x]

    return indexes if indexes else False

target = 'dont'
sentence = 'we dont need no education we dont need no thought control no we dont'

print(find_indexes(sentence, target))
>> [1, 6, 13]
print(find_indexes(sentence, 'johndoe'))
>> False

I'm looking to change the method to something like this, without the need to write the comprehension twice:

def find_indexes(sentence, target):
    return [index for index, x in enumerate(sentence.split()) if target == x] \ 
       if [index for index, x in enumerate(sentence.split()) if target == x] else False

Write a procedure that takes a string of words separated by spaces (assume no punctuation or capitalization), together with a ”target” word, and shows the position of the target word in the string of words.

For example, if the string is:

we dont need no education we dont need no thought control no we dont

and the target is the word:

”dont”

then your procedure should return the list 1, 6, 13 because ”dont” appears at the 1st, 6th, and 13th position in the string. (We start counting positions of words in the string from 0.) Your procedure should return False if the target word doesn’t appear in the string

5
  • 1
    return [index for index, x in enumerate(sentence.split()) if target == x] or False Commented Oct 12, 2017 at 13:28
  • 3
    Note: Explicitly returning False is fairly pointless. Just return the listcomp itself; if it's empty, it will behave as a falsy value, and 99% of the time, that's fine (or better than fine, since it still acts like a sequence, so you can blindly do a for loop over the result and it will simply not do anything). It's generally not Pythonic to insist on actual True/False values, just allow implicit truthiness testing to do its thing. Commented Oct 12, 2017 at 13:29
  • 5
    Why do you think False is a better return value than []? An empty list will be treated as False in any context where you should be using a Boolean value (and I'm explicitly counting foo == False as something you should not be doing). Commented Oct 12, 2017 at 13:30
  • 1
    +1 to the comments above, if your function should return a list let it always return one, not a mixture of lists and bools Commented Oct 12, 2017 at 13:31
  • It was in the question I was supplying the answer for that asked for it to be False Commented Oct 12, 2017 at 13:31

4 Answers 4

4

Just return the empty list if there are no matches found.

def find_indexes(sentence, target):
    return [index for index, x in enumerate(sentence.split()) if target == x]

indices = find_indexes("hi there bob", "bob")
if not indices:
    print("No matches found")
else:
    for i in indices:
        print("Found match at {}".format(i))
Sign up to request clarification or add additional context in comments.

1 Comment

Indeed. I recognized it as the word "is", but didn't take the next step to remembering it is a keyword.
3

You can short-circuit with or:

def find_indexes(sentence, target):
    return [i for i, x in enumerate(sentence.split()) if target == x] or False

Comments

3
return [...] or False

The or operator returns one of its operands; the first if the first is truthy, otherwise the second.

Comments

1

Returning False isn't only pointless, it makes the code larger and more brittle.

Every time you use the original find_indexes function, you need to check if it's a boolean or a list. Otherwise, your code might raise a TypeError if no index is found:

def find_indexes(sentence, target):
    indices = [index for index, x in enumerate(sentence.split()) if target == x]
    return indices if indices else False

sentence = 'we dont need no education we dont need no thought control no we dont'

for index in find_indexes(sentence, "not_found"):
    print(index)

It throws:

TypeError: 'bool' object is not iterable

As suggested by @chepner, simply return an empty list if no index is found : an empty list is falsey in Python anyway. You need one line less in your function and in every susequent call.

Finally, since Python is a dynamic language, it's really important to use adequate function names in order to write readable code. If your function is called find_indexes, it should return an iterable. If it's called is_a_substring, then it should return a boolean.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.