У меня есть вложенный список кортежей из 97510 таких значений:
a = [ (1,2,3), (3,4,5), (5,4,2)]
каждое первое значение (index = 0) является уникальным, и мне нужно найти другие элементы индекса = 0, которые имеют одинаковый индекс = 1 элементы. В этом примере мне нужно найти второй и третий кортежи, где второй элемент "4" общий.
Как мне это сделать?
Если вы хотите найти все совпадения:
>>> 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
Вот один из способов сделать это:
>>> 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)]})
Это приведет к созданию словаря списков, в котором все элементы с одним и тем же вторым значением находятся в одном списке, с этим значением в качестве ключа.
Другая альтернатива:
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)]
Обратите внимание, что вы также можете использовать 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))
filter
с лямбдой -[item for item from a if item[1] == 4]
. Это, на мой взгляд, лучше читать.