Сравните два списка A, B в Python, найдите все элементы в A, соответствующие одному и тому же числу в B

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

A = [5, 7, 9, 12, 8, 16, 25]
B = [2, 1, 3, 2, 3, 1, 4]

Я хотел бы получить

[7,16] corresponding to the number 1 of listB
[5, 12] corresponding to the number 2 of listB
[9, 8] corresponding to the number 3 of listB
[25] corresponding to the number 4 of listB

A и B всегда будут иметь одинаковую длину.

Ответ 1

Вы можете использовать zip для создания кортежей, которые состоят из одного элемента из обоих списков, затем сортируют их и, наконец, группируют их по значению от B:

>>> from itertools import groupby
>>> A = [5, 7, 9, 12, 8, 16, 25]
>>> B = [2, 1, 3, 2, 3, 1, 4]
>>> for k, g in groupby(sorted(zip(B,A)), key=lambda x: x[0]):
...     print('{} corresponds to {}'.format([x[1] for x in g], k))
... 
[7, 16] corresponds to 1
[5, 12] corresponds to 2
[8, 9] corresponds to 3
[25] corresponds to 4

В выше zip(B, A) возвращается итерабельность кортежей, где каждый кортеж имеет элемент из B и A:

>>> list(zip(B,A))
[(2, 5), (1, 7), (3, 9), (2, 12), (3, 8), (1, 16), (4, 25)]

Затем результат сортировки сортируется так, что все кортежи с одинаковым значением из B находятся рядом друг с другом:

>>> sorted(zip(B,A))
[(1, 7), (1, 16), (2, 5), (2, 12), (3, 8), (3, 9), (4, 25)]

Результат сортировки передается groupby, который группирует кортежи на основе значения, возвращаемого ключевой функцией, в этом случае первый элемент в кортеже. Результат повторяется с (key, group) кортежами, где группа итерабельна для элементов:

>>> [(k, list(g)) for k, g in groupby(sorted(zip(B,A)), key=lambda x: x[0])]
[(1, [(1, 7), (1, 16)]), (2, [(2, 5), (2, 12)]), (3, [(3, 8), (3, 9)]), (4, [(4, 25)])]

Ответ 2

Попробуйте этот подход.

unique = set(B)    # Creates a set of unique entries in B
for u in unique:
    # Find indices of unique entry u
    indices = [i for i, x in enumerate(B) if x == u]

    # Pull out these indices in A
    corrEntry = [A[i] for i in indices]  

    # Do something with the data, in this case print what OP wants
    print('{} corresponds to the number {} of list B'.format(corrEntry , B[indices[0]]))

Он находит уникальные записи в B с помощью функции set. Затем мы прокручиваем эти уникальные записи. Первое понимание списка (для indices) находит индексы записей в B, которые соответствуют этой уникальной записи. Второй сохраняет значение в этих индексов.

Ответ 3

Я думаю, вы можете использовать этот код:

A = [5, 7, 9, 12, 8, 16, 25]
B = [2, 1, 3, 2, 3, 1, 4]

d = {}

for a, b in zip(A, B):
    d.setdefault(b, [])
    d[b].append(a)

for k, v in sorted(d.items()):
    print('{} corresponds {}'.format(v, k))

Каждая клавиша словаря будет элементом B, и связанное с ней значение будет именно таким списком.

Ответ 4

Альтернатива с использованием collections.defaultdict:

import collections as ct

dd = ct.defaultdict(list)
for a, b in zip(A, B):
    dd[b].append(a)

dd
# defaultdict(list, {1: [7, 16], 2: [5, 12], 3: [9, 8], 4: [25]})

Пример результатов печати:

for k, v in sorted(dd.items()):
    print("{} corresponding to the number {} of listB".format(v, k))

# [7, 16] corresponding to the number 1 of listB
# [5, 12] corresponding to the number 2 of listB
# [9, 8] corresponding to the number 3 of listB
# [25] corresponding to the number 4 of listB

Ответ 5

A = [5, 7, 9, 12, 8, 16, 25]
B = [2, 1, 3, 2, 3, 1, 4]

Создайте определенную функцию, которая принимает два списка (A, B) и число (n) в качестве аргументов. Выберите все элементы в A, которые имеют ту же позицию списка, что и элементы в B, эквивалентные n. zip используется для сопряжения элементов из A и B с одинаковой позицией списка. Эта функция использует представление списка для выбора элементов из A.

>>> def f(A, B, n):
    return [a for a, b in zip(A,B) if b == n]

>>> f(A, B, 2)
[5, 12]
>>> 

Функция может быть записана без понимания списка:

def g(A, B, n):
    result = []
    for a, b in zip(A, B):
        if b == n:
            result.append(a)
    return result

Используя fuctools.partial, аргументы списка могут быть исправлены:

import functools
f_AB = functools.partial(f, A, B)

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

>>> f_AB(3)
[9, 8]

>>> numbers = [3, 4, 2]
>>> for n in numbers:
    print (n, f_AB(n))

(3, [9, 8])
(4, [25])
(2, [5, 12])
>>>