7
votes

Comment code une fonction similaire à iteroTools.Product à Python 2.5

J'ai une liste de tuples, par exemple: xxx pré>

et souhaitez générer toutes les permutations avec un élément de chaque tuple. P>

1,3,7
1,5,7
1,7,7
...
3,9,7


2 commentaires

Notez que vous devrez redéfinir votre A. Lorsque vous dites A = [(1,2,3), (3,5,7,9), (7)] le ( 7) à la fin est évalué comme un entier, pas un tuple. Par conséquent, ce n'est pas démonérable, et produit (* a) lancera TypeError. Si vous dites a = (1,2,3), (3,5,7,9), (7,)] alors produit (* a) fonctionnera .


Ok, je vois, mais c'était un exemple trop simple. J'ai une liste de listes de tuples à 3 nombres. Mais je veux retirer la liste extérieure et obtenir A = listes de tuples à 3 nombres. Comment je fais ça? Mieux vaut en faire une nouvelle question de python débutant je pense.


4 Réponses :


13
votes

docs de itheroTools.Production code> avoir un exemple de la manière de la mettre en œuvre dans PY2.5:

def product(*args, **kwds):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    pools = map(tuple, args) * kwds.get('repeat', 1)
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)


1 commentaires

Correction de cela, j'ai accidentellement copié l'exemple des documents PY3.1.



4
votes

La documentation ITERTOOLS contient le code complet montrant que chaque fonction est équivalente à. Le produit est ici . < / p>


1 commentaires

Merci, je devais me demander de me demander.



8
votes
def product(*iterables):
    """ Equivalent of itertools.product for versions < 2.6,
        which does NOT build intermediate results.
        Omitted 'repeat' option.
        product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    """
    nIters = len(iterables)
    lstLenths = []
    lstRemaining = [1]
    for i in xrange(nIters-1,-1,-1):
        m = len(iterables[i])
        lstLenths.insert(0, m)
        lstRemaining.insert(0, m * lstRemaining[0])
    nProducts = lstRemaining.pop(0)

    for p in xrange(nProducts):
        lstVals = []

        for i in xrange(nIters):
            j = p/lstRemaining[i]%lstLenths[i]
            lstVals.append(iterables[i][j])
        yield tuple(lstVals)

0 commentaires

5
votes

Lorsque vous jouez avec des générateurs, j'ai aussi trouvé une version de itheroTools.Product code>, et il est presque aussi rapide que la version de la bibliothèque (natif), tout en étant 100% compatible avec elle et Ne construit pas les résultats intermédiaires:

>>> import itertools as itt
>>> timeit for _ in itt.product(range(20), range(3), range(150)): pass
1000 loops, best of 3: 221 µs per loop
>>> timeit for _ in product(range(20), range(3), range(150)): pass
1000 loops, best of 3: 1.14 ms per loop


2 commentaires

Utiliser un essai / sauf pour mettre fin à une boucle n'est pas génial. Vous comptez essentiellement sur une erreur pour courte circuit votre boucle.


Je ne suis pas d'accord avec l'accusation que je abuse des conditions "Erreur" pour quitter la boucle - STOVITÉTRAITATION est une condition valide pour vérifier dans une construction de boucle car elle est utilisée en interne chaque fois qu'une boucle est terminée. Notez que des exceptions et STOVITÉTÉTRAITRATION en particulier ont une utilisation légèrement plus large en Python qu'en C ++, cf. aussi le zen de python.