2

I have a list of lists, and will do a search on it which will yield just one result. The following code works but isn't intuitive because it doesn't really express the intent of what I'm trying to do... it looks like I'm trying to return a list, and just happen to want to return the first item in the last: which isn't true, as I always will want just one item, never a list. Anything more intuitive here?

game = [g for g in games if g.num==5 and re.search("ucla", g.a_name, re.I)][0]
appleLover
  • 14,835
  • 9
  • 33
  • 50
  • possible duplicate of [Shortcut OR-chain applied on list](http://stackoverflow.com/questions/18208730/shortcut-or-chain-applied-on-list) – Alfe Sep 26 '13 at 10:00
  • This is also about this topic: http://stackoverflow.com/questions/1077307/why-is-there-no-firstiterable-built-in-function-in-python – Alfe Sep 26 '13 at 10:02

2 Answers2

3

Sadly, there isn't a built-in method in Python for searching in a list using a helper function.

However, you can use a generator expression and make it stop on first match instead on iterating over the remaining list even if a match is already found.

game = next(g for g in games if g.num==5 and re.search("ucla", g.a_name, re.I))

Or maybe more functional approach (this is not equivalent to the previous one on Python 2.x, because it generates the whole list, and doesn't stop at the first matching element. On Python 3.x filter returns an iterator and behavior is same).

game = next(filter(lambda g: g.num==5 and re.search("ucla", g.a_name, re.I), games))

It's a matter of preference whether the filter is clearer or not. BDFL prefers comprehension tho.

utdemir
  • 26,532
  • 10
  • 62
  • 81
  • 1
    In Python 2.x, filter builds a list first, it does too much work after the first match has been found. – pts Sep 27 '13 at 09:47
1
list_games = [g for g in games if g.num==5 and re.search("ucla", g.a_name, re.I)]
game = list_games[0]

You can explicitly assign the first element of that list to your variable game. That makes it a bit clearer.

Paco
  • 4,520
  • 3
  • 29
  • 53