Операция над каждой парой элементов в списке
используя Python, я хотел бы сравнить каждую возможную пару в списке.
предположим, что я
my_list = [1,2,3,4]
Я хотел бы сделать операцию (назовем ее foo) на каждой комбинации из 2 элементов из списка.
конечный результат должен быть таким же, как
foo(1,1)
foo(1,2)
...
foo(4,3)
foo(4,4)
моей первой мыслью было дважды итерировать по списку вручную, но это, кажется, не очень подходящие для Python.
3 ответа:
проверить
product()
наitertools
модуль. Он делает именно то, что вы описываете.import itertools my_list = [1,2,3,4] for pair in itertools.product(my_list, repeat=2): foo(*pair)
это эквивалентно:
my_list = [1,2,3,4] for x in my_list: for y in my_list: foo(x, y)
Edit: есть две очень похожие функции,
permutations()
иcombinations()
. Чтобы проиллюстрировать, чем они отличаются:
product()
генерирует все возможные пары элементов, включая все дубликаты:1,1 1,2 1,3 1,4 2,1 2,2 2,3 2,4 3,1 3,2 3,3 3,4 4,1 4,2 4,3 4,4
permutations()
создает все уникальные порядки каждой уникальной пары элементов, исключаяx,x
продублирую:. 1,2 1,3 1,4 2,1 . 2,3 2,4 3,1 3,2 . 3,4 4,1 4,2 4,3 .
наконец,
combinations()
генерирует только каждую уникальную пару элементов, в лексикографическом порядке:. 1,2 1,3 1,4 . . 2,3 2,4 . . . 3,4 . . . .
все три из этих функций были введены в Python 2.6.
у меня была аналогичная проблема и нашел решение здесь. Он работает без необходимости импортировать модуль.
предположим, что список выглядит так:
people = ["Lisa","Pam","Phil","John"]
упрощенное однострочное решение будет выглядеть так.
все возможные пары, в том числе дубликатов:
result = [foo(p1, p2) for p1 in people for p2 in people]
все возможные пары, исключая дубликаты:
result = [foo(p1, p2) for p1 in people for p2 in people if p1 != p2]
уникальный пар, где заказывать не имеет значения:
result = [foo(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))]
в случае, если вы не хотите работать, но просто получить пары, удаление функции
foo
и использование только кортежа было бы достаточно.все возможные пары, в том числе дубликатов:
list_of_pairs = [(p1, p2) for p1 in people for p2 in people]
результат:
('Lisa', 'Lisa') ('Lisa', 'Pam') ('Lisa', 'Phil') ('Lisa', 'John') ('Pam', 'Lisa') ('Pam', 'Pam') ('Pam', 'Phil') ('Pam', 'John') ('Phil', 'Lisa') ('Phil', 'Pam') ('Phil', 'Phil') ('Phil', 'John') ('John', 'Lisa') ('John', 'Pam') ('John', 'Phil') ('John', 'John')
все возможные пары, исключая дубликаты:
list_of_pairs = [(p1, p2) for p1 in people for p2 in people if p1 != p2]
результат:
('Lisa', 'Pam') ('Lisa', 'Phil') ('Lisa', 'John') ('Pam', 'Lisa') ('Pam', 'Phil') ('Pam', 'John') ('Phil', 'Lisa') ('Phil', 'Pam') ('Phil', 'John') ('John', 'Lisa') ('John', 'Pam') ('John', 'Phil')
уникальный пар, где заказывать не имеет значения:
list_of_pairs = [(people[p1], people[p2]) for p1 in range(len(people)) for p2 in range(p1+1,len(people))]
результат:
('Lisa', 'Pam') ('Lisa', 'Phil') ('Lisa', 'John') ('Pam', 'Phil') ('Pam', 'John') ('Phil', 'John')
Edit: после переделки, чтобы упростить это решение, я понял, что это тот же подход, что и Адам Розенфилд. Я надеюсь, что более широкое объяснение поможет некоторым понять его лучше.
если вы просто вызываете функцию, вы не можете сделать намного лучше, чем:
for i in my_list: for j in my_list: foo(i, j)
если вы хотите получить список результатов вызова функции, вы можете сделать:
[foo(i, j) for i my_list for j in my_list]
который вернет вам список результатов применения
foo(i, j)
к каждой возможной паре(i, j)
.