Находите общие элементы списка по каким-то критериям? - PullRequest
2 голосов
/ 16 июня 2020

Входные данные представлены в виде списка кортежей,

left_corners = [((380, 456), 1), ((1129, 456), 2), ((354, 328), 3), ((1137, 325), 4)]
right_corners = [((784, 456), 1), ((1535, 456), 2), ((778, 328), 3)]

Обычными элементами будут те, которые имеют второй элемент кортежа как 1, 2, 3, поэтому я бы хотел, чтобы окончательное представление было выглядят так -

[(((380, 456), 1),((784, 456), 1)), (((1129, 456), 2),((1535, 456), 2)), (((354, 328), 3), ((778, 328), 3))]

Я не могу придумать решение без нескольких циклов (цикл по обоим элементам и добавление элементов, которые имеют тот же второй элемент в общий список). Есть ли способ более pythoni c? Я открыт для других представлений об этом в numpy или что-то в этом роде.

Допущения: Мы можем предположить, что оба списка отсортированы, причем ключ является вторым элементом списка, но либо left_corners или right_corners может иметь больше элементов, чем другой

Ответы [ 5 ]

3 голосов
/ 16 июня 2020

Если вы используете словари, вы могли бы сделать что-то более эффективное

group_lists = {}
for corner in (left_corners+right_corners):
  group_lists[corner[1]] = group_lists.get(corner[1], [])
  group_lists[corner[1]].append(corner)

output = [group_lists[k] for k in group_lists]

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

output = [tuple(group_lists[k]) for k in group_lists]
1 голос
/ 16 июня 2020
first, second = (left_corners, right_corners) if len(left_corners) > len(right_corners) else (right_corners, left_corners)

[(i, j) for i in first for j in second  if i[1] == j[1]]

Я предположил, что второй элемент (ключ для объединения кортежей) может быть чем угодно, а не просто 1, 2, 3

Другое предположение состоит в том, что второй элемент отсортирован, но может пропускать числа, например, если это не так, тогда zip - это путь к go.

left_corners = [(X, 1), (Y, 2), (Z, 3)]
right_corners = [(A, 1), (B, 3)]
1 голос
/ 16 июня 2020

Может быть (не уверен, так как проблема не очень четко сформулирована) это то, что вы хотите:

good_corners = [ [ t for t in corners if t[1] in {1,2,3}] for corners in (left_corners, right_corners) ]
result = list(zip(*good_corners))
0 голосов
/ 17 июня 2020

У меня это сработало очень хорошо

combined_list = list(zip(left_corners, right_corners))
0 голосов
/ 16 июня 2020

Как насчет понимания списка?

a = [k for k in left_corners if k[1] in [1,2,3]] + [k for k in right_corners if k[1] in [1,2,3]]

вывод:

[((380, 456), 1), ((1129, 456), 2), ((354, 328), 3), ((784, 456), 1), ((1535, 456), 2), ((778, 328), 3)]

Это действительно только в том случае, если порядок не имеет значения. Если ему нужен порядок, вы можете отсортировать его с помощью лямбда-функции:

sorted(a, key=lambda x: x[1])

вывод:

[((380, 456), 1), ((784, 456), 1), ((1129, 456), 2), ((1535, 456), 2), ((354, 328), 3), ((778, 328), 3)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...