Как получить те кортежи из списка кортежей, которые имеют одинаковое второе значение? - PullRequest
0 голосов
/ 31 января 2019

У меня есть список кортежей, которые выглядят следующим образом:

entities = [('tmp', 'warm'), ('loc', 'blr'), ('cap', 'blr'), ('aps', 'yes'), ('date', '12-10-2018')]

Я хочу сохранить те кортежи, которые имеют одинаковые значения second .Как вы можете видеть, кортежи ('loc', 'blr') и ('cap', 'blr') имеют одно и то же второе значение.

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

Эточто я пробовал, но это не работает, как ожидалось

duplicate = []
for i in range(len(entities)):
    for j in range(1, len(entities)):
        if entities[i][1] == entities[j][1]:
            duplicate.append([entities[i][1], entities[j][1]])
            break

Но я получаю все кортежи, как будто все кортежи имеют одинаковое второе значение.Как я могу это сделать?

Желаемый вывод

('loc', 'blr'), ('cap', 'blr')

Ответы [ 3 ]

0 голосов
/ 31 января 2019

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

grouped = {}
for k, v in entities:
    grouped[v].setdefault(k, []).append((k, v))
for _, tuples in grouped.items():
    if len(tuples) > 2:
        print(tuples)

все пары с одинаковым вторым значением будут сгруппированы под разными ключами

0 голосов
/ 31 января 2019

Вы можете использовать O ( n log n ) itertools.groupby (требуется предварительная сортировка списка ввода), но O ( n) collections.Counter достаточно:

from collections import Counter
from operator import itemgetter

# construct dictionary mapping second value to count
c = Counter(map(itemgetter(1), entities))

# filter for second values with count > 1
dups = {value for value, count in c.items() if count > 1}

# filter entities with second value in dups
res = [entity for entity in entities if entity[1] in dups]

print(res)
# [('loc', 'blr'), ('cap', 'blr')]
0 голосов
/ 31 января 2019

Вы можете сгруппировать списки с общими вторыми элементами следующим образом:

s = sorted(entities, key = lambda x: x[1])
[list(v) for k,v in groupby(s, key=lambda x: x[1])]

[[('date', '12-10-2018')],
 [('loc', 'blr'), ('cap', 'blr')],
 [('tmp', 'warm')],
 [('aps', 'yes')]]

Если производительность является проблемой, рассмотрите возможность использования operator.itemgetter:

from operator import itemgetter
s = sorted(entities, key = itemgetter(1))
[list(v) for k,v in groupby(s, key = itemgetter(1))]

[[('date', '12-10-2018')],
 [('loc', 'blr'), ('cap', 'blr')],
 [('tmp', 'warm')],
 [('aps', 'yes')]]

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

[i for i in l if len(i)>1]
[[('loc', 'blr'), ('cap', 'blr')]]

Я предложил этот ответ, чтобы таким образом вы могли расширить его до n commonэлементы на втором месте, так как их может быть больше 2.

...