Koko
Koko

Reputation: 479

A more concise way to write this Python code

In Python, I'd like to test for the existence of a keyword in the output of a Linux command. The keywords to test for would be passed as a list as shown below. I've not spent a lot of time with Python so brute-force approach is below. Is there a cleaner way to write this?

def test_result (result, mykeys):

  hit = 0
  for keyword in mykeys:
     if keyword in result:
        hit = 1
        print "found a match for " + keyword

  if hit == 1:
     return True


result = "grep says awk"
mykeys = ['sed', 'foo', 'awk']
result = test_result (result, mykeys)

Upvotes: 3

Views: 176

Answers (4)

munk
munk

Reputation: 12983

Your function does two things, printing and returning the result. You could break them up like so:

def test_result(result, mykeys):
    return [k in result for k in mykeys]

def print_results(results):
    for result in results:
        print("found a match for " + result)

test_result will return a list with all the found keys, or an empty list. The empty list is falsey, so you can use it for whatever tests you want. The print_results is only needed if you actually want to print, otherwise you can use the result in some other function.

If you only want to check for the presence and don't care about which key you found, you can do something like:

def test_result(result, my_keys):
    return any(map(lambda k: k in result, mykeys))

If you're using python3 (as you should be), I believe this will be lazy and only evaluate as much of the list as necessary.

See A more concise way to write this Python code for a more concise version of this last function.

Upvotes: 2

Rushy Panchal
Rushy Panchal

Reputation: 17532

You can use a regular expression to accomplish this. A regular expression of the form a|b|c matches any of a, b or c. So, you'd want something of the form:

import re
p = re.compile('|'.join(mykeys))
return bool(p.search(result))

p.search(result) searches the entire string for a match of the regular expression; it returns a match (which is truth-y) if present and returns None (which is false-y) otherwise. Converting the result to bool gives True if it matches and False otherwise.

Putting this together, you'd have:

import re

def test_result(result, mykeys):
  p = re.compile('|'.join(mykeys))
  return bool(p.search(result))

You can also make this more concise by not pre-compiling the regular expression; this should be fine if it's a one-time use:

def test_result(result, mykeys):
  return bool(re.search('|'.join(mykeys), result))

For reference, read about Python's re library.

Upvotes: 2

hdiogenes
hdiogenes

Reputation: 759

The any built-in will do it.

def test_result(result, mykeys):
    return any(key in result for key in mykeys)

Upvotes: 4

Olivier Melançon
Olivier Melançon

Reputation: 22314

To search for an element in a list, you can use a for-else statement. In particular, this allows to return the found element.

def test_result (result, mykeys):
   for keyword in mykeys:
     if keyword in result: break
   else:
       return None
   return keyword

print(test_result("grep says awk", ['sed', 'foo', 'awk'])) # 'awk'
print(test_result("grep says awk", ['bar', 'foo'])) # None

Upvotes: 0

Related Questions