I have a list like that:
lst = ['something', 'foo1', 'bar1', 'blabla', 'foo2']
Is it possible to get the index of the first item starting with "foo" (foo1) using regular expressions and lst.index()
like:
ind = lst.index("some_regex_for_the_item_startin开发者_运维知识库g_with_foo") ?
I know I can create a counter and a for loop and use method startswith()
.
I am curious if I miss some shorter and more elegant way.
I think that it's ok and you can use startswith method if it do what you really want(i am not sure that you really need regEx here - however code below can be easily modified to use regEx):
data = ['text', 'foo2', 'foo1', 'sample']
indeces = (i for i,val in enumerate(data) if val.startswith('foo'))
Or with regex:
from re import match
data = ['text', 'foo2', 'foo1', 'sample']
indeces = (i for i,val in enumerate(data) if match('foo', val))
No, unfortunately there is no key
parameter for list.index
.
Having that a solution could have been
# warning: NOT working code
result = L.index(True, key=lambda x: regexp.match(x) is not None)
Moreover given that I just discovered that lambda
apparently is considered in the python community an abomination I'm not sure if more key
parameters are going to be added in the future.
There is no way to do it using the lst.index
, however here is an alternative method that you may find more elegant than a for loop:
try:
ind = (i for i, v in enumerate(lst) if v.startswith("foo")).next()
except StopIteration:
ind = -1 # or however you want to say that the item wasn't found
As senderle pointed out in a comment, this can be shortened by using the next()
built-in function (2.6+) with a default value to shorten this to one line:
ind = next((i for i, v in enumerate(lst) if v.startswith("foo")), -1)
l = ['something', 'foo1', 'bar1', 'blabla', 'foo2']
l.index(filter(lambda x:x.startswith('foo'),l)[0])
It would be kind of cool to have something like this built in. Python doesn't though. There are a few interesting solutions using itertools. (These also made me wish for a itertools.takewhile_false
. If it existed, these would be more readable.)
>>> from itertools import takewhile
>>> import re
>>> m = re.compile('foo.*')
>>> print len(tuple(itertools.takewhile(lambda x: not m.match(x), lst)))
1
That was my first idea, but it requires you to create a temporary tuple and take its length. Then it occurred to me that you could just do a simple sum, and avoid the temporary list:
>>> print sum(1 for _ in takewhile(lambda x: not m.match(x), lst))
1
But that's also somewhat cumbersome. I prefer to avoid throw-away variables when possible. Let's try this again.
>>> sum(takewhile(bool, (not m.match(x) for x in lst)))
1
Much better.
精彩评论