4 votes

Python : quelques produits spéciaux d'une liste donnée

Je voudrais trouver un moyen pour les produits possibles de la liste donnée. Ci-dessous, j'ai un exemple

Jusqu'à présent, j'ai essayé ceci :

for p in itertools.product(the_list, repeat=2):
        print p

Mais cela renvoie toutes les possibilités qui peuvent être générées à partir de la liste donnée. Pouvez-vous m'aider à générer l'exemple suivant ?

Un exemple :

the_list=['A1','A2','A3','B1','B2','B3','C1','C2','C3','D1','D2','D3']
The results should be: 
['A1A2','A1B2','A1C2','A1D2','A2A3','A2B3','A2C3','A2D3','A3A1','A3B1','A3C1','A3D1'
 'B1A2,'B2A3'...
 'C1A2'...']

En principe, les lettres majuscules désignent l'État et les chiffres la séquence. Ainsi, si l'on commence par A1, on ne peut continuer qu'avec un État portant le numéro 2, par exemple d'abord A1, puis A2 ou B2 ou C2 ou D2. Le système est également circulaire, ce qui signifie que A3 est suivi soit par A1, B1, C1 ou D1.

2voto

Volatility Points 12668
l=['A1','A2','A3','B1','B2','B3','C1','C2','C3','D1','D2','D3']
result = [i + j for i in l for j in l if int(j[1]) == int(i[1]) + 1 or (j[1] == '1' and i[1] == '3')]
print(result)

Cette sortie :

['A1A2', 'A1B2', 'A1C2', 'A1D2', 'A2A3', 'A2B3', 'A2C3', 'A2D3', 'A3A1', 'A3B1', 'A3C1', 'A3D1', 'B1A2', 'B1B2', 'B1C2', 'B1D2', 'B2A3', 'B2B3', 'B2C3', 'B2D3', 'B3A1', 'B3B1', 'B3C1', 'B3D1', 'C1A2', 'C1B2', 'C1C2', 'C1D2', 'C2A3', 'C2B3', 'C2C3', 'C2D3', 'C3A1', 'C3B1', 'C3C1', 'C3D1', 'D1A2', 'D1B2', 'D1C2', 'D1D2', 'D2A3', 'D2B3', 'D2C3', 'D2D3', 'D3A1', 'D3B1', 'D3C1', 'D3D1']

Si vous préférez la lisibilité à la compacité, décomposez le texte en une seule ligne

l=['A1','A2','A3','B1','B2','B3','C1','C2','C3','D1','D2','D3']
result = []
for i in l:
    for j in l:
        if int(j[1]) == int(i[1]) + 1 or (j[1] == '1' and i[1] == '3'):
            result.append(i+j)
print(result)

Il en résulte la même chose.

1voto

kojiro Points 24374

Sur la base de votre liste actuelle, il n'y a pas beaucoup de valeurs à éliminer si vous voulez simplement obtenir toutes les permutations et filtrer les indésirables après coup. Faites-le paresseusement et les valeurs que vous filtrerez seront beaucoup moins courantes que celles que vous conserverez. (J'utiliserai une compréhension de liste pour plus de transparence - transformez-la en une expression de générateur dans votre code réel).

>>> from itertools import permutations
>>> [''.join(x) for x in permutations(l, 2) if int(x[0][1]) % 3 == int(x[1][1]) - 1]
['A1A2', 'A1B2', 'A1C2', 'A1D2', 'A2A3', 'A2B3', 'A2C3', 'A2D3', 'A3A1', 'A3B1', 'A3C1', 'A3D1', 'B1A2', 'B1B2', 'B1C2', 'B1D2', 'B2A3', 'B2B3', 'B2C3', 'B2D3', 'B3A1', 'B3B1', 'B3C1', 'B3D1', 'C1A2', 'C1B2', 'C1C2', 'C1D2', 'C2A3', 'C2B3', 'C2C3', 'C2D3', 'C3A1', 'C3B1', 'C3C1', 'C3D1', 'D1A2', 'D1B2', 'D1C2', 'D1D2', 'D2A3', 'D2B3', 'D2C3', 'D2D3', 'D3A1', 'D3B1', 'D3C1', 'D3D1']

Mise à jour pour répondre au commentaire de John : En supposant que chaque État a la même taille de séquence :

>>> seq_size = len([x for x in l if x[0] == 'A']) # Get the length of the sequence of A
>>> [''.join(x) for x in permutations(l, 2) if int(x[0][1:]) % seq_size == int(x[1][1:]) - 1]

Mise à jour de généraliser pour la prochaine série de commentaires de John :

#!env python

'''Get all the permutations of pieces up to a certain size
    where the sequence numbers of each piece occur in order, cyclically.
    So for a permutation_size of 5, 1->2, 2->3, 3->4, 4->5, 5->1.'''

from string import uppercase
from itertools import permutations

num_states = 5
seq_size = 13
group_size = 3

the_list = [char + str(1 + num) for char in uppercase[:num_states] for num in xrange(seq_size)]

def groupFilter(pieces):
    '''True for a list whose sequence is in order. False otherwise.'''
    ints = [int(piece.lstrip(uppercase)) for piece in pieces]
    offset = ints[0] % seq_size
    for i, piece in enumerate(ints):
        if offset + i != piece % seq_size:
            return False
    return True

[''.join(group) for group in permutations(the_list, group_size) if groupFilter(group)]

0voto

Cheyne H Points 111

Vous pourriez le diviser par séquence, en ayant

first = ['A1', 'B1', 'C1', 'D1']
second = ['A2', 'B2', 'C2', 'D2']
...

Ensuite, le produit de deux listes consécutives devrait vous donner ce que vous voulez (si je comprends bien votre question...).

0voto

RocketDonkey Points 16205

Juste au cas où vous voudriez quelque chose qui puisse fonctionner avec itertools.product Vous pouvez également essayer ceci (nous serons ravis d'apporter des modifications si cela ne correspond pas à vos données "réelles" - c'est un problème intéressant :) ). Cela pourrait être résumé en moins de lignes, mais cela perd beaucoup en lisibilité, donc j'espère que cela sera quelque peu utile :

from itertools import groupby, product
from operator import itemgetter

the_list = ['A1','A2','A3','B1','B2','B3','C1','C2','C3','D1','D2','D3']

# In order to work properly with groupby, we sort the list by the
# number at the end of the string
s = sorted(the_list, key=itemgetter(-1))

# Now we create a list of lists, each sub-list containing values
# with the same ending number (i.e. ['A1', 'B1', 'C1', 'D1'])
j = [list(g) for _, g in groupby(s, key=itemgetter(-1))]

# Now we create our final list
results = []

# Here we iterate through our grouped lists, using product
# similar to how you did before to create the combined strings
for index, r in enumerate(j):

    # This is the piece that lets us 'loop' the list -
    # on the first iteration, the value is -(3)+1+0 = -2,
    # which we use as our list index. This will return the item
    # 'ahead' of the current one in our main list, and when it
    # reaches the last (index=2) item, the value is -(3)+1+2 = 0 (beginning)
    inc = -len(j) + 1 + index

    # Now we just iterate through the items in our sub-list, pairing with
    # the items in the 'next' sub-list
    for val in r:
        results += [k+v for k, v in product([val], j[inc])]

print results

Sortie :

['A1A2', 'A1B2', 'A1C2', 'A1D2', 
 'B1A2', 'B1B2', 'B1C2', 'B1D2', 
 'C1A2', 'C1B2', 'C1C2', 'C1D2', 
 'D1A2', 'D1B2', 'D1C2', 'D1D2', '
  A2A3', 'A2B3', 'A2C3', 'A2D3', 
 'B2A3', 'B2B3', 'B2C3', 'B2D3', 
 'C2A3', 'C2B3', 'C2C3', 'C2D3', 
 'D2A3', 'D2B3', 'D2C3', 'D2D3', 
 'A3A1', 'A3B1', 'A3C1', 'A3D1', 
 'B3A1', 'B3B1', 'B3C1', 'B3D1', 
 'C3A1', 'C3B1', 'C3C1', 'C3D1', 
 'D3A1', 'D3B1', 'D3C1', 'D3D1']

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X