3

The problem is simple enough. I'm writing a function which returns true if the string contains any of the illegal names.

line is a string.

illegal_names is an iterable.

def has_illegal_item(line, illegal_names):
    illegal_items_found = False
    for item in illegal_names:
        if item in line:
            illegal_items_found = True
            break
    return illegal_items_found

So this works fine, but it seems a bit clumsy and long-winded. Can anyone suggest a neater and more pythonic way to write this? Could I use a list comprehension or regex?

1
  • Unless you know something about the string or illegal names (eg. whitespace separated tokens) I don't think you can use list comprehension Commented Sep 4, 2012 at 11:04

3 Answers 3

6
any(name in line for name in illegal_names)
Sign up to request clarification or add additional context in comments.

4 Comments

Perfect! Thanks! I even used the word any in my question's title, so perhaps I should've found this.
The only caveat about simply using in is that it's a substring test, not a word test: "Robert" in "Sarah Robertson" is True. But that may be what you wanted anyway.
@DSM: true. It's easy enough to turn it into a baseline word check: any(name in re.findall(r"\w+", line) for name in illegal_name). Word splitting can be an NLP-complete problem, though.
Thanks DSM, I expected that behaviour and it is what I want. I'm setting the list of illegal names as a constant, so I can add whitespaces manually as required.
1

let's have a look on following sample:

line = "This is my sample line with an illegal item: FOO"
illegal_names = ['FOO', 'BAR']

and you want now to find out whether your line contains one of the illegal names, then you do this with the widespread List Comprehension and a length check:

is_correct = not bool(len([ hit for hit in illegal_names if hit in line ]))
# or
is_correct = len([ hit for hit in illegal_names if hit in line ]) == 0

Pretty easy, short and in relation to other lambda version easy to read and unterstand.

-Colin-

Comments

0

I go with @larsmans solution, but there another ways of doing it.

def check_names(line, names):
    #names should be set
    parsed_line = set(line.replace(',', '').split())
    return bool(parsed_line.intersection(names))

This can also be written using lambda

In [57]: x = lambda line, names: bool(set(line.replace(",", "").split()).intersection(names))

In [58]: x("python runs in linux", set(["python"]))
Out[58]: True

lamdba version can be overkill of readability

2 Comments

Ah intersection - interesting, but more complicated.
@JamesBradbury: not complicated but different way to see the same problem.

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.