web-dev-qa-db-fra.com

La façon Pythonique de générer des paires

Je veux quelque chose comme du code ci-dessous, mais un style "Pythonic" ou en utilisant une bibliothèque standard:

def combinations(a,b):
    for i in a:
        for j in b:
             yield(i,j)
32
Dima

Ce ne sont pas vraiment des "combinaisons" au sens de la combinatoire, ce sont plutôt des éléments du produit cartésien de a et b. La fonction dans la bibliothèque standard pour générer ces paires est itertools.product() :

for i, j in itertools.product(a, b):
    # whatever
36
Sven Marnach

Comme l'a dit @Sven, votre code tente d'obtenir toutes les paires d'éléments ordonnées des listes a et b. Dans ce cas, itertools.product(a,b) est ce que vous voulez. Si à la place vous voulez réellement des "combinaisons", qui sont toutes des paires non ordonnées d'éléments distincts de la liste a, alors vous voulez itertools.combinations(a,2).

>>> for pair in itertools.combinations([1,2,3,4],2):
...    print pair
...
(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
27
Rob

La bibliothèque itertools possède des fonctions combinatoires. Comme l'a déclaré Sven, itertools.product serait la fonction appropriée dans ce cas:

list(itertools.product('ab', 'cd'))
[('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd')]
7
Håvard

Une expression de générateur imbriquée fonctionnera également:

product = ((i, j) for i in a for j in b)
for i, j in product:
    # ...
7
mhyfritz
>>>a=[1,2,3]
>>>b=[4,5,6]
>>>Zip(a,b)
[(1, 4), (2, 5), (3, 6)] 
4
fransua

Créer un ensemble de paires (paires, impaires)

>>> a = { (i,j) for i in range(0,10,2) for j in range(1,10,2)}  
>>> a
{(4, 7), (6, 9), (0, 7), (2, 1), (8, 9), (0, 3), (2, 5), (8, 5), (4, 9), (6, 7), (2, 9), (8, 1), (6, 3), (4, 1), (4, 5), (0, 5), (2, 3), (8, 7), (6, 5), (0, 1), (2, 7), (8, 3), (6, 1), (4, 3), (0, 9)}

def combinations(lista, listb):
    return { (i,j) for i in lista for j in listb }

>>> combinations([1,3,5,6],[11,21,133,134,443])
{(1, 21), (5, 133), (5, 11), (5, 134), (6, 11), (6, 134), (1, 443), (3, 11), (6, 21), (3, 21), (1, 133), (1, 134), (5, 21), (3, 134), (5, 443), (6, 443), (1, 11), (3, 443), (6, 133), (3, 133)}
1
wwright

Une question que nous pourrions nous poser est de savoir si vous souhaitez générer toutes les paires ordonnées ou toutes les paires non ordonnées. L'expression du générateur imbriqué fournie dans la réponse de mhyfritz vous donnera toutes les paires ordonnées.

Si vous voulez que toutes les paires non ordonnées (c'est-à-dire que (1, 2) et (2, 1) comptent comme la même paire), alors vous devez filtrer les doublons. Un moyen simple de le faire est d'ajouter un conditionnel à la fin de l'expression du générateur comme ceci:

myList= [1, 2, 3, 4, 5]
unorderedPairGenerator = ((x, y) for x in myList for y in myList if y > x)
for pair in unorderedPairGenerator:
    print(pair)
#(1, 2)
#(1, 3)
#(1, 4)
#(1, 5)
#(2, 3)
#(2, 4)
#(2, 5)
#(3, 4)
#(3, 5)
#(4, 5)

En passant, on m'a posé une question similaire à celle-ci dans une interview logicielle, où ils voulaient que je génère toutes les paires à partir d'une liste de nombres (sans utiliser une fonction de bibliothèque). Au début, j'ai généré toutes les paires ordonnées, puis ils m'ont demandé de ne générer que les paires non ordonnées. Être capable de travailler avec des permutations et des combinaisons est une compétence de codage assez essentielle!

1
lonknex