Как найти индекс элемента в списке, ища элемент с регулярным выражением в Python? - PullRequest
3 голосов
/ 08 июля 2011

У меня есть такой список:

lst = ['something', 'foo1', 'bar1', 'blabla', 'foo2']

Можно ли получить индекс первого элемента, начиная с "foo" (foo1), используя регулярные выражения и lst.index(), например:

ind = lst.index("some_regex_for_the_item_starting_with_foo") ?

Я знаю, что могу создать счетчик и цикл for и использовать метод startswith(). Мне любопытно, если я пропущу какой-то более короткий и элегантный способ.

Ответы [ 5 ]

3 голосов
/ 08 июля 2011

Я думаю, что это нормально, и вы можете использовать метод startwith, если он делает то, что вы действительно хотите (я не уверен, что вам действительно нужно regEx здесь - однако код ниже можно легко изменить, чтобы использовать regEx):

data = ['text', 'foo2', 'foo1', 'sample']
indeces = (i for i,val in enumerate(data) if val.startswith('foo'))

Или с регулярным выражением:

from re import match
data = ['text', 'foo2', 'foo1', 'sample']
indeces = (i for i,val in enumerate(data) if match('foo', val))
1 голос
/ 08 июля 2011

Нет, к сожалению, для list.index нет параметра key.Наличие такого решения могло бы быть

# warning: NOT working code
result = L.index(True, key=lambda x: regexp.match(x) is not None)

Более того, учитывая, что я только что обнаружил, что lambda явно считается в сообществе питонов мерзостью, я не уверен, будет ли больше key параметров.добавлено в будущем.

1 голос
/ 08 июля 2011

Нет способа сделать это, используя lst.index, однако вот альтернативный метод, который вы можете найти более элегантным, чем цикл for:

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

Как указал отправитель в комментарии,это можно сократить, используя встроенную функцию next() (2.6+) со значением по умолчанию, чтобы сократить это до одной строки:

ind = next((i for i, v in enumerate(lst) if v.startswith("foo")), -1)
0 голосов
/ 08 июля 2011
l = ['something', 'foo1', 'bar1', 'blabla', 'foo2']
l.index(filter(lambda x:x.startswith('foo'),l)[0])
0 голосов
/ 08 июля 2011

Было бы круто иметь что-то подобное в этом. Python не делает этого. Есть несколько интересных решений, использующих itertools. (Это также заставило меня пожелать itertools.takewhile_false. Если бы оно существовало, они были бы более читабельными.)

>>> from itertools import takewhile
>>> import re
>>> m = re.compile('foo.*')
>>> print len(tuple(itertools.takewhile(lambda x: not m.match(x), lst)))
1

Это была моя первая идея, но она требует от вас создания временного кортежа и его длины. Тогда мне пришло в голову, что вы можете просто сделать простую сумму и избежать временного списка:

>>> print sum(1 for _ in takewhile(lambda x: not m.match(x), lst))
1

Но это также несколько громоздко. Я предпочитаю избегать одноразовых переменных, когда это возможно. Давайте попробуем это снова.

>>> sum(takewhile(bool, (not m.match(x) for x in lst)))
1

Намного лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...