permutations et remplacements de valeurs dans une liste

5 réponses
Avatar
Kevin Denis
Bonjour,

je cherche à remplacer des valeurs d'une liste par d'autres.

Mettons que j'ai une liste de données:
a = [[1,'a', '3'],[2, 'b','1'], [3,'b','3']]

J'ai une série de correspondances:
La première valeur vaut soit 10, soit 100, soit 1000.
La seconde valeur est soit rouge, soit bleu
La troisième valeur est soit cheval, soit vache.

Je veux la liste des permutations possibles, par exemple obtenir:
10, rouge, cheval
100, bleu, vache
1000, bleu, cheval
10, rouge, vache
100, bleu, cheval
1000, rouge, vache
etc...

Je peux permuter facilement avec itertools:
for i in itertools.permutations([10,100,1000]):
for j in itertools.permutations(['rouge', 'bleu']):
for k in itertools.permutations(['cheval','vache']):

mais je ne vois pas de manière simple comment remplacer chacune des
valeurs initiales par leurs finales.

J'espère être clair,
Merci
--
Kevin

5 réponses

Avatar
Damien Wyart
* Kevin Denis in fr.comp.lang.python:
je cherche à remplacer des valeurs d'une liste par d'autres.

Mettons que j'ai une liste de données:
a = [[1,'a', '3'],[2, 'b','1'], [3,'b','3']]

J'ai une série de correspondances:
La première valeur vaut soit 10, soit 100, soit 1000.
La seconde valeur est soit rouge, soit bleu
La troisième valeur est soit cheval, soit vache.



Voici ce que je propose :

a = [[1,'a', '3'],[2, 'b','1'], [3,'b','3']]

maps = ({1:10, 2:100, 3:1000}, {'a':'rouge', 'b':'bleu'},
{'1':'cheval', '3':'vache'})

for l in a:
for i in range(len(l)):
l[i] = maps[i][l[i]]

print a

Je veux la liste des permutations possibles, par exemple obtenir:
10, rouge, cheval
100, bleu, vache
1000, bleu, cheval
10, rouge, vache
100, bleu, cheval
1000, rouge, vache
etc...

Je peux permuter facilement avec itertools:
for i in itertools.permutations([10,100,1000]):
for j in itertools.permutations(['rouge', 'bleu']):
for k in itertools.permutations(['cheval','vache']):

mais je ne vois pas de manière simple comment remplacer chacune des
valeurs initiales par leurs finales.
J'espère être clair,



J'avoue que je ne vois pas super bien le lien entre la liste de départ,
à trois éléments, et la liste des permutations, bien plus longue...

Dans tous les cas, se baser sur un dict pour faire la correspondance me
paraît bien adapté et mon exemple est sans doute adaptable sur ton cas
des permutations.

--
DW
Avatar
Kevin Denis
Le 28-03-2013, Damien Wyart a écrit :
mais je ne vois pas de manière simple comment remplacer chacune des
valeurs initiales par leurs finales.
J'espère être clair,



J'avoue que je ne vois pas super bien le lien entre la liste de départ,
à trois éléments, et la liste des permutations, bien plus longue...



Je vais essayer de simplifier pour être plus clair.

J'ai un fichier avec des id numériques.
Je ne sais pas à quoi correspondent ces id.
Je connais toutefois les données qui ont servies à créer ces id.
Je sais par exemple que j'ai deux couleurs, bleu et rouge.
Dans mon fichier de départ, j'ai deux id '1' et '2'. Je sais que
cette id correspond à la couleur.

Mon idée, c'est donc de remplacer toutes les id 1 par bleu et 2 par rouge.
Je regarde si ça semble cohérent. Puis je remplace l'id 1 par rouge
et 2 par bleu et je regarde si c'est cohérent. Si je n'avais qu'une id et
deux valeurs, je le ferais à la main.

Dans mon cas, je n'ai pas qu'une id, j'en ai trois (numérique et texte).
Et chacune de ces id peut prendre plusieurs possibilités. Ca fait
beaucoup de combinaisons.

Dans tous les cas, se baser sur un dict pour faire la correspondance me
paraît bien adapté et mon exemple est sans doute adaptable sur ton cas
des permutations.



L'ordre des enregistrements est important pour garantir une cohérence.
--
Kevin
Avatar
Damien Wyart
Si j'ai bien compris, quelque chose comme ça (basé sur ma première
réponse et sur tes boucles avec permutations()) devrait convenir :

import itertools

a = ((1,'a', '3'), (2, 'b','1'), (3, 'b', '3'))

print a, "n"

for perm1 in itertools.permutations([10, 100, 1000]):
for perm2 in itertools.permutations(['rouge', 'bleu']):
for perm3 in itertools.permutations(['cheval', 'vache']):
maps = []
maps.append(dict(zip([1, 2, 3], perm1)))
maps.append(dict(zip(['a', 'b'], perm2)))
maps.append(dict(zip(['1', '3'], perm3)))

print maps

l = []
for elt in a:
e = []
for i in range(len(elt)):
e.append(maps[i][elt[i]])
l.append(e)

print l, "n"

C'est un peu verbeux pour bien montrer comment cela fonctionne...

Note qu'au sens strict, je ne remplace pas les éléments de la liste
initiale (sinon je ne l'ai plus pour les remplacements suivants).

--
DW
Avatar
Kevin Denis
Le 28-03-2013, Damien Wyart a écrit :
Si j'ai bien compris, quelque chose comme ça (basé sur ma première
réponse et sur tes boucles avec permutations()) devrait convenir :



Yep merci beaucoup

maps.append(dict(zip([1, 2, 3], perm1)))



Du coup, je découvre http://docs.python.org/2/library/functions.html#zip
qui correspond bien à ce que je souhaite faire, plutôt qu'une longue liste
de if/else.

C'est un peu verbeux pour bien montrer comment cela fonctionne...



Merci
--
Kevin
Avatar
Pierre Maurette
Kevin Denis :
Le 28-03-2013, Damien Wyart a écrit :
mais je ne vois pas de manière simple comment remplacer chacune des
valeurs initiales par leurs finales.
J'espère être clair,



J'avoue que je ne vois pas super bien le lien entre la liste de départ,
à trois éléments, et la liste des permutations, bien plus longue...



Je vais essayer de simplifier pour être plus clair.

J'ai un fichier avec des id numériques.
Je ne sais pas à quoi correspondent ces id.
Je connais toutefois les données qui ont servies à créer ces id.
Je sais par exemple que j'ai deux couleurs, bleu et rouge.
Dans mon fichier de départ, j'ai deux id '1' et '2'. Je sais que
cette id correspond à la couleur.

Mon idée, c'est donc de remplacer toutes les id 1 par bleu et 2 par rouge.
Je regarde si ça semble cohérent. Puis je remplace l'id 1 par rouge
et 2 par bleu et je regarde si c'est cohérent. Si je n'avais qu'une id et
deux valeurs, je le ferais à la main.

Dans mon cas, je n'ai pas qu'une id, j'en ai trois (numérique et texte).
Et chacune de ces id peut prendre plusieurs possibilités. Ca fait
beaucoup de combinaisons.

Dans tous les cas, se baser sur un dict pour faire la correspondance me
paraît bien adapté et mon exemple est sans doute adaptable sur ton cas
des permutations.



L'ordre des enregistrements est important pour garantir une cohérence.



Si j'ai bien tout compris la demande, vous pouvez essayer ça:

import itertools
a = [[1,'a', '3'], [2, 'b','1'], [3,'b','3'], [1,'a', '3'], [2,
'b','1'], [3,'b','3']]

inVals = ((1, 2, 3), ('a','b'), ('1', '3'))
outVals = ((10, 100, 1000), ('rouge', 'bleu'), ('cheval', 'vache'))

inValsInverse = [dict(zip(L, range(len(L)))) for L in inVals]
for f in itertools.product(itertools.permutations(range(3))
, itertools.permutations(range(2))
, itertools.permutations(range(2))):
print 'n', 30 * '-', 'n', f, 'n'
for elem in a:
print [outVals[i][f[i][inValsInverse[i][x]]] for i, x in
enumerate(elem)]

Il y a plus simple, plus élégant, on peut automatiser la création de f
à partir de inVals, celle de inVals à partir de a (à mon avis, outVals
doit être fait à la mimine et en cohérence avec inVals) mais ça devient
un peu confus, surtout en écoutant Notre Président tenter de ne pas
l'être trop (confus)...

--
Pierre Maurette