2
\$\begingroup\$

I want to check if some line ends with any substring defined in some list. Is there a better way than following one?

endsA = ['foo', 'bar', 'fur', 'beer']
endsB = ['door', ... ]
def checkEnds(line, ends):
 for end in ends:
 if line.endswith(end):
 return True
....
if checkEnds(line, endsA):
 do_something()
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Mar 30, 2016 at 15:06
\$\endgroup\$
0

2 Answers 2

9
\$\begingroup\$

Yes, there is! Generator comprehensions and the any function to the rescue.

def checkEnds(line, ends):
 return any(line.endswith(end) for end in ends)

Just like the original code, this only checks as many line.endswith(end) as necessary, returning True on the first True result.

answered Mar 30, 2016 at 15:33
\$\endgroup\$
4
  • \$\begingroup\$ Thank you (+1). I am wondering will endsWith perform to each element of ends or till first True? \$\endgroup\$ Commented Mar 30, 2016 at 15:40
  • 2
    \$\begingroup\$ Written in this form, it will stop as soon as possible. \$\endgroup\$ Commented Mar 30, 2016 at 16:13
  • 1
    \$\begingroup\$ @SjoerdJobPostmus: That would be a good detail to have as a note in your answer, IMO. +1 \$\endgroup\$ Commented Mar 30, 2016 at 21:52
  • \$\begingroup\$ @ZachGates: Added it to the answer instead. \$\endgroup\$ Commented Mar 31, 2016 at 7:48
3
\$\begingroup\$

@Sjoerd's solution using any() is definitely the way to go.

I'd also like to point out a recommendation in PEP 8:

  • Be consistent in return statements. Either all return statements in a function should return an expression, or none of them should. If any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable).

In your case, this means that if you were to keep your for loop, you should also write an explicit return False instead of returning None by falling off the end of the function.

I would also suggest a better name for your function: any_suffix_matches(suffixes, string). This name leads to more readable code in the caller, and clearly conveys the idea that the function is a true-false test. It also conforms to the PEP 8 naming convention.

if any_suffix_matches(endsA, line):
 do_something()

Note that I've also swapped the order of the parameters. Since "contains any of these suffixes" is the test, and the test is applied to some string, the suffixes should be placed closer to the function name. You see this design convention in re.search(pattern, string), for example.

answered Mar 31, 2016 at 7:19
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.