2010-01-30 6 views
5

J'ai une liste L = [a, b, c] et je veux générer une liste de tuples:multiplication

[(a,a), (a,b), (a,c), (b,a), (b,b), (b,c)...] 

J'ai essayé de faire L * L mais cela n'a pas fonctionné. Quelqu'un peut-il me dire comment l'obtenir en python.

+0

Ce genre de "produit" est aussi appelé "produit cartésien" ou "produit direct" (je ne suis pas sûr qu'un terme soit plus approprié ici mais le doc Python lui-même utilise un "produit cartésien"). – MatrixFrog

Répondre

13

Le module itertools contient un certain nombre de fonctions utiles pour ce genre de chose. On dirait que vous cherchez peut-être product:

>>> import itertools 
>>> L = [1,2,3] 
>>> itertools.product(L,L) 
<itertools.product object at 0x83788> 
>>> list(_) 
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)] 
7

Jetez un oeil au module itertools, qui fournit un membre product.

L =[1,2,3] 

import itertools 
res = list(itertools.product(L,L)) 
print(res) 

donne:

[(1,1),(1,2),(1,3),(2,1), .... and so on] 
22

Vous pouvez le faire avec une compréhension de la liste:

[ (x,y) for x in L for y in L] 

modifier

Vous pouvez également utiliser itertools.product comme d'autres suggéré, mais seulement si vous utilisez 2.6 et plus. La compréhension de la liste fonctionnera toutes les versions de Python à partir de la version 2.0. Si vous utilisez itertools.product, sachez qu'il renvoie un générateur au lieu d'une liste, vous devrez donc le convertir (en fonction de ce que vous voulez en faire).

+0

Merci pour la clarification. – Schitti

0

x = [a, b, c] y = [] pour objet x: pour item2 en x: y.append ((point, item2))

peut-être pas la façon dont Pythonic mais travaillant

0

Ok j'ai essayé:

L2 = [(x, y) pour x en L pour x dans L] et cela a carré L.

Est-ce la meilleure façon de faire cela? Je m'attendrais à ce que L * L travaille en python.

+0

Mauvaises attentes - 'sequence * sequence' n'est pas ** défini ** (seulement' sequence * int', ce qui fait quelque chose ** très ** différent! -). –

+0

Oups, a écrit ceci avant que j'ai vu les réponses. S'il vous plaît ignorer – Schitti

3

Deux alternatives principales:

>>> L = ['a', 'b', 'c'] 
>>> import itertools 
>>> list(itertools.product(L, L)) 
[('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'b'), ('b', 'c'), ('c', 'a'), ('c', 'b'), ('c', 'c')] 
>>> [(one, two) for one in L for two in L] 
[('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'b'), ('b', 'c'), ('c', 'a'), ('c', 'b'), ('c', 'c')] 
>>> 

l'ancien a besoin Python 2.6 ou mieux - ce dernier fonctionne dans presque toute version Python que vous pourriez être lié à.

+0

Utiliser itertools me semble étrange si vous allez tout simplement de convertir directement à une liste de toute façon.La compréhension de la liste est probablement plus efficace, tout aussi lisible et probablement plus facile à maintenir en ce sens qu'il y a des ajustements que vous pouvez faire directement à l'expression. Plus l'abstraction peut signifier plus d'inflexibilité, et le but est de cacher les détails que vous espérez (mais ne pouvez pas être sûrs), vous n'aurez plus jamais à vous inquiéter. – Steve314

0

La façon la plus ancienne de le faire serait:

def perm(L): 
    result = [] 
    for i in L: 
     for j in L: 
      result.append((i,j)) 
    return result 

Cela a une durée d'exécution de O (n^2) et est donc assez lent, mais vous pourriez considérer être le style « vintage » code.

+0

Toutes les approches à ceci ont au mieux O (n^2) runtime, la raison étant qu'ils doivent tous générer des tuples O (n^2). L'utilisation d'un itérateur tel que itertools vous permet de différer certains de ces travaux, mais vous ne pouvez pas l'éviter complètement. Votre approche peut même être O (n^3) - l'ajout aux listes peut bien être O (n) plutôt que O (1) en raison de problèmes de réallocation de mémoire, bien que je ne m'en souvienne pas avec certitude. Je * pense * que la liste Python utilise un tableau redimensionnable - * pas * une liste chaînée. Il pourrait y avoir une sorte d'optimisation append, cependant. Une compréhension de liste * probablement * préalloue tout le tableau au début. – Steve314