фильтровать элементы из списка списков в Python? - PullRequest
7 голосов
/ 17 апреля 2010

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

a = [[1,2,3],[4,5,6]]

предположим, что я хочу сохранить только те элементы, у которых сумма в списке больше, чем N. Я попытался написать:

filter(lambda x, y, z: x + y + z >= N, a)

но я получаю ошибку:

 <lambda>() takes exactly 3 arguments (1 given)

Как я могу выполнить итерацию при назначении значений каждого элемента x, y и z? Что-то вроде zip, но для произвольно длинных списков.

спасибо,

p.s. Я знаю, что могу написать это используя: filter (lambda x: sum (x) ..., a), но это не главное, представьте, что это были не числа, а произвольные элементы, и я хотел присвоить их значения именам переменных. 1014 *

Ответы [ 7 ]

33 голосов
/ 17 апреля 2010

Использование lambda с filter глупо, когда у нас есть другие доступные методы.

В этом случае я бы, вероятно, решил бы конкретную проблему таким образом (или используя эквивалентное выражение генератора)

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> [item for item in a if sum(item) > 10]
[[4, 5, 6]]

или, если мне нужно распаковать, как

>>> [(x, y, z) for x, y, z in a if (x + y) ** z > 30]
[(4, 5, 6)]

Если бы я действительно нуждался в функции, я мог бы использовать распаковку кортежей аргументов (кстати, она удалена в Python 3.x, поскольку люди не очень часто ее используют): lambda (x, y, z): x + y + z берет кортеж и распаковывает его элементы как x, y и z. (Обратите внимание, что вы также можете использовать это в def, то есть: def f((x, y, z)): return x + y + z.)

Конечно, вы можете использовать распаковку стиля присваивания (def f(item): x, y, z = item; return x + y + z) и индексирование (lambda item: item[0] + item[1] + item[2]) во всех версиях Python.

10 голосов
/ 17 апреля 2010

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

>>> a = [[1,2,3],[4,5,6]]
>>> N = 10
>>> filter(lambda (i, j, k): i + j + k > N, a)
[[4, 5, 6]]

Если вы укажете «лямбда i, j, k», как вы пытались это сделать, вы говорите, что лямбда получит три аргумента. Но фильтр даст лямбду каждому элементу, то есть одному подсписку за раз (таким образом, ошибка, которую вы получили). Заключая аргументы лямбда в круглые скобки, вы говорите, что лямбда получит один аргумент, но вы также называете каждый из его компонентов.

1 голос
/ 17 апреля 2010

Вы можете сделать что-то вроде

>>> a=[[1,2,3],[4,5,6]]
>>> filter(lambda (x,y,z),: x+y+z>6, a)
[[4, 5, 6]]

Использование синтаксиса деконструкции.

0 голосов
/ 17 апреля 2010

Хорошо, очевидно, вы знаете, что можете использовать sum. Цель того, что вы пытаетесь сделать, кажется немного расплывчатой, но я думаю, что синтаксис необязательных параметров может помочь вам или, по крайней мере, вдохновит вас. Если вы поместите * перед параметром, он создаст кортеж всего себя и всех оставшихся параметров. Если вы поместите ** перед ним, вы получите словарь.

Чтобы увидеть это:

def print_test(a,b,c,*d):
    print a
    print b
    print c
    print d

print_test(1,2,3,4,5,6)

печать

1
2
3
(4, 5, 6)

Вы также можете использовать этот синтаксис с lambda.

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

Редактировать: Ах, теперь я понимаю, что вы ищете. Я думаю, что вы хотите:

lambda (a, b, c): a+b+c > N
0 голосов
/ 17 апреля 2010

Как насчет этого?

filter(lambda b : reduce(lambda x, y : x + y, b) >= N, a)

Это не отвечает на заданный вопрос, я знаю, но оно работает для произвольно длинных списков и произвольно длинных подсписков и поддерживает любую операцию, которая работает в reduce().

0 голосов
/ 17 апреля 2010

Используйте функцию вместо лямбды, затем myVar = a[0] и т. Д.

0 голосов
/ 17 апреля 2010

Попробуйте что-то вроде этого:

filter(lambda a: a[0] + a[1] + a[2] >= N, a)
...