0

Possible Duplicate:
Return the first item in a list matching a condition

How to easily grab the "matching" list element using list comprehension? e.g. I've a list and I'm looking for a element that starts with a a certain string. That's easy to do:

>>> lines = ['AHP Buildlife number', 'NIT-Version-Default-v0.16.0', 'E_release v2.3.14.0']
>>> [ x.strip() for x in lines if x.startswith('NIT-Version-Default') ]
['NIT-Version-Default-v0.16.0']

But how can I do the same from in a if statement so that the matching list-element can be used for further processing; some thing like this:

>>> if [ x.strip() for x in lines if x.startswith('NSS-Checkin-Default') ]:
...   ver = x.split('-')[-1].strip()
...   print ver

So, that it return v0.16.0 as the version number. This obviously doesn't work but hopefully you get the idea what I'm trying to do. Any idea how to do that? Cheers!!

PS. You are welcome to improve the question or the title.

Community
  • 1
  • 1
MacUsers
  • 2,091
  • 3
  • 35
  • 56
  • Note that if you didn't want to use that value later, just check if one existed, the best solution would be `any()`. – Gareth Latty Jan 18 '13 at 17:43

4 Answers4

2

If you're looking for only one element:

x = next(x.strip() for x in lines if x.startswith('NSS-Checkin-Default'))
ver = x.split('-')[-1].strip()

Note that I've used a generator expression (a for b in c if d), instead a list comprehension [a for b in c if d]. This way the iteration over lines will only be done for as long as actually needed (in this case, until the first element is found).

If no element is found, next will raise StopIteration.


If you additionally want to make sure that there's exactly one element (or exactly N elements for some fixed N), you could write it this way (assign to a tuple):

(x,) = (x.strip() for x in lines if x.startswith('NSS-Checkin-Default')

In that case you'll have a ValueError if the generator expression will yield too few or too many elements. This is called "tuple unpacking".

See also:

What is the best way to get the first item from an iterable matching a condition?

Community
  • 1
  • 1
Kos
  • 70,399
  • 25
  • 169
  • 233
0

Simple: your list comprehension returns a list with one element, so you just access the element: thelist[0]

To take from your example:

lines = ['AHP Buildlife number', 'NIT-Version-Default-v0.16.0', 'E_release v2.3.14.0']
results = [ x.strip() for x in lines if x.startswith('NIT-Version-Default') ]
ver = results[0].split('-')[-1].strip()
print ver
Alex
  • 7,639
  • 3
  • 45
  • 58
0
>>> for each in lines:
...     match=re.search("(^NIT-Version-Default).*(v[0-9.]+)",each)
...     if match:
...             print match.group(2)
... 
v0.16.0
Suku
  • 3,820
  • 1
  • 21
  • 23
0

See the map function. I don't see a vital necessity of comprehensions, instead:

map(lambda x: x.split('-')[-1].strip(),
        filter(lambda x: x.startswith('NIT'), lines)) 
Vidul
  • 10,128
  • 2
  • 18
  • 20
  • `map(lambda x: f(x), seq)` is just a longer way of writing `[f(x) for x in seq]`. – Kos Jan 18 '13 at 17:45
  • @Kos, sure it is, unless map needs a lambda (your example). – Vidul Jan 18 '13 at 17:53
  • A convention I follow is "use map/filter when you already have the functions, use comprehensions otherwise". Unless you're using the var-arg variant of `map`. – Kos Jan 18 '13 at 17:58