0

Say I have a list in python as

some_list = [(1,'a'),(2,'b')]

Is there a way I can shorten the following code:

def someMethod(some_list, some_string):
    for value in some_list:
        if 'some_string' is value[1]:
            print 'do_something'
KKa
  • 408
  • 4
  • 19
  • 2
    *Aside*: Please note that `is` is almost certainly the wrong operator for this. Use `if 'some_string' == value[1]'` instead. http://stackoverflow.com/questions/1504717/why-does-comparing-strings-in-python-using-either-or-is-sometimes-produce http://stackoverflow.com/questions/2988017/string-comparison-in-python-is-vs – Robᵩ Sep 22 '14 at 03:18
  • 2
    It would be difficult to shorten that code and maintain its clarity. Why do you want it to be shorter? – Robᵩ Sep 22 '14 at 03:20

4 Answers4

1

Use the any function:

def someMethod(some_list, some_string):
    if any(x[1] == 'some_string' for x in some_list):
        print 'do_something'

The any function returns true if any element of its argument is true. In this case, the argument is a generator which produces a sequence of Boolean values, so the entire list doesn't need to be examined: any will stop running the generator as soon as it finds a matching value.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • It's a bit hard to tell from the code sample in the question, but I suspect that Kartik wants to "do something" for _each_ tuple in `some_list` that passes the test. And I assume the test should be `x[1] == some_string` rather than `x[1] == 'some_string'`, but his code sample is a little ambiguous... – PM 2Ring Sep 22 '14 at 05:09
  • When `'some_string'` is obviously a placeholder, it's trivial to replace it with the correct item, whether that is a literal string or a variable. Although on second reading, it does seem pretty obvious that there is no intent to only do *one* thing if any item matches, so this answer is not the solution. – chepner Sep 22 '14 at 12:10
0

Yes, you can flatten the list and check it at the same time.

def someMethod(some_list, some_string):
    some_list = [value for item in some_list for value in item if value == some_string]
    for _ in some_list:
        print 'do_something'

If you are looking for shorter lengthwise, then you can do the following (less pythonic):

def someMethod(some_list, some_string):    
    some_list = [value for item in some_list for value in item if value == some_string]
    for _ in some_list: print 'do_something'
A.J. Uppal
  • 19,117
  • 6
  • 45
  • 76
  • But kartik _only_ wants to check a specific field in each tuple, not all fields, so flattening is not appropriate here. – PM 2Ring Sep 22 '14 at 05:00
0

I suppose this might be shorter:

def someMethod(some_list, some_string):
    for value in itertools.ifilter(lambda x: x[1]=='some_string', some_list):
        print 'do_something'

Or even:

def someMethod(some_list, some_string):
    print '\n'.join('do_something' for x in some_list if x[1]=='some_string')   

But, while some of the suggestions are shorter than your code, none of them are more clear. Clarity should be your goal here, not brevity.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • 1
    I agree that clarity is *much* more important than character count, but find the `any` version more obvious that itertools, lambda, join. It also short-circuits. – msw Sep 22 '14 at 04:43
-1

You have a list of tuples and a string, and you want to do_something() every time the string appears in the second part of a tuple.

def someMethod(some_list, some_string):
    [do_something() for _, s in some_list if s == some_string]

The trick is to get at the second part of the tuple by unpacking it into _, s, where _ is a throwaway variable.

Unfortunately you can't execute the statement print 'do_something' inside a list comprehension. However, you can call the print function, which will need to be explicitly imported if you're using Python 2:

from __future__ import print_function
def someMethod(some_list, some_string):
    [print('do_something') for _, s in some_list if s == some_string]
Community
  • 1
  • 1
sjy
  • 2,702
  • 1
  • 21
  • 22
  • 2
    Don't use a list comprehension simply to replace a for-loop if you don't care about the resulting list. – chepner Sep 22 '14 at 04:01
  • And why unpack all fields of a tuple when you only want one of them? – PM 2Ring Sep 22 '14 at 05:02
  • 1
    Aside from it being an anti-pattern in Python, it is inefficient, since you have to spend the time allocating a new list object only to throw it away immediately. – chepner Sep 22 '14 at 12:10