поиск по вложенному списку в python - PullRequest
1 голос
/ 20 июня 2011

У меня есть вложенный список кортежей из 97510 значений, подобных этому:

a = [ (1,2,3), (3,4,5), (5,4,2)]

каждое первое значение (index = 0) уникально, и мне нужно найти другие элементы index = 0, которые имеют такой же индекс = 1 элементы В этом примере мне нужно найти второй и третий кортежи, где второй элемент '4' является общим.

Как мне это сделать?

Ответы [ 4 ]

4 голосов
/ 20 июня 2011

Если вы хотите найти все совпадения:

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> for inner in a:
...     d[inner[1]].append(inner)
... 
>>> d
defaultdict(<type 'list'>, {2: [(1, 2, 3)], 4: [(3, 4, 5), (5, 4, 2)]})
>>> d[4]
[(3, 4, 5), (5, 4, 2)]

Если вы хотите выбрать все совпадения для определенного второго значения:

>>> filter(lambda inner: inner[1] == 4, a)
[(3, 4, 5), (5, 4, 2)]

Редактировать : Как указано в комментариях, предпочтительным является понимание списка, поскольку оно более эффективно для такой работы:

>>> [inner for inner in a if inner[1] == 4]
[(3, 4, 5), (5, 4, 2)]

Использование timeit показывает, что понимание списка примерно в 2,5 раза быстрее (на моем компьютере в любом случае):

>>> timeit.timeit('[inner for inner in a if inner[1] == 4]', 'a=[(1,2,3), (3,4,5), (5, 4, 2)]')
2.5041549205780029
>>> timeit.timeit('filter(lambda inner: inner[1] == 4, a)', 'a=[(1,2,3), (3,4,5), (5, 4, 2)]')
6.328679084777832
3 голосов
/ 20 июня 2011

Вот один из способов сделать это:

>>> result = defaultdict(list)
>>> for item in a:
>>>     result[item[1]].append(item)
>>> result
defaultdict(<type 'list'>, {2: [(1, 2, 3)], 4: [(3, 4, 5), (5, 4, 2)]})

В результате появится словарь списков, в котором все элементы с одинаковым вторым значением находятся в одном списке с этим значением в качестве ключа.

1 голос
/ 20 июня 2011

Другая альтернатива:

from operator import itemgetter
from itertools import groupby

a = [ (1,2,3), (3,4,5), (5,4,2)]
b = groupby(sorted(a), itemgetter(1))
for val, group in b:
    print val, list(group)
# 2 [(1, 2, 3)]
# 4 [(3, 4, 5), (5, 4, 2)]
1 голос
/ 20 июня 2011

Обратите внимание, что вы также можете использовать groupby :

from itertools import groupby

data = [ (1,2,3), (3,4,5), (5,4,2)]
res = groupby(sorted(data), key=lambda x: x[1])

Отредактировано согласно комментарию

Поигрался с проблемой и нашел еще одно решение - но не лучшее, но:

inputVals = [(1,2,3), (3,4,5), (5,4,2), (2,2,3), (7,3,1)]
for val in set(x[1] for x in inputVals):   
    print val, list(set(sval for sval in inputVals if sval[1] == val))
...