пятница, 17 апреля 2009 г.

Поиск значения в списке

Итак в продолжение темы рецептов - ищем элемент в списке, как это не странно Python 2.5 этого делать нормально не умеет.
Раньше я делал это примерно так

a = None
for x in list:
if pred(x):
a = x

Очевидно что это не удобно. Как это обойти я подсмотрел здесь (там описано гораздо больше вариантов, но все они плохо работают с случаем когда ничего не найдено)

Итак делаем функцию find (которая должна бы быть в стандартной библиотеке языка)

def find(f, seq):
"""Return first item in sequence where f(item) == True."""
for item in seq:
if f(item):
return item

Дальше поиск прост

a = find(lambda x: x.id == 5, values) #will find value with id == 5 or None if nothing found

Стоит отметить что в 2.6 версии эта проблема решена и все гораздо проще (спасибо @ mishok13 за пример)

next((x for x in seq if pred(x)), None)
или для нашего примера
next((x for x in values if x.id == 5), None)

Какие есть еще более изящные варианты?

5 комментариев:

  1. как вариант:

    >>> some = [1,2,3,4,5]
    >>> func = lambda x: x == 3
    >>> filter(func, some)
    [3]
    >>> func2 = lambda x: x == 100
    >>> filter(func2, some)
    []

    ОтветитьУдалить
  2. >>> some = [1,2,3,4,5]
    >>> [ x for x in some if x==3]

    ОтветитьУдалить
  3. Комментаторы упустили основною мысль -- нужен или первый найденный обьект (один) или некий другой обьект.
    Вот рецепт:
    >>> seq = range(10)
    >>> ([x for x in seq if x == 3] or [42])[0]
    3
    >>> ([x for x in seq if x == 13] or [42])[0]
    42
    Для любителей filter, тоже самое:
    >>> (filter(lambda x: x == 3, seq) or [42])[0]
    3
    >>> (filter(lambda x: x == 13, seq) or [42])[0]
    42
    Но всё таки, лучше использовать builtin next, как я и советовал. Имплементация на питоне элементарна.

    ОтветитьУдалить
  4. вопрос значит правильно ставить надо. list comprehension IMHO самый что ни на есть питоновский way to go. остальное - детали.

    ОтветитьУдалить
  5. угу, у меня тоже такая функция написана.

    ОтветитьУдалить