Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Remplacer les occurrences de __TRUC__ dans une chaîne par les éléments d'une séquence

21 réponses
Avatar
Francois
Bonjour à tous,


J'ai une chaîne de caractères ch qui contient par exemple 20
occurrences de la chaîne "__TRUC__". Elle en contient 20 occurrences
exactement car ch a été construite comme ça. Et j'ai une séquence seq
contenant 20 chaînes, comme par exemple :

seq = ['a0','a1',...,'a19']


Comment faire de manière la plus simple possible pour remplacer :
- la première occurrence de "__TRUC__" dans ch par 'a0'
- la deuxième occurrence de "__TRUC__" dans ch par 'a1'
.
.
.
- la vingtième occurrence de "__TRUC__" dans ch par 'a19' ?


Je sais par exemple que ch.replace("__TRUC__","xxx") remplace
toutes les occurrences de "__TRUC__" dans ch par "xxx". J'aimerais bien
savoir si on peut faire sans trop se fatiguer la même chose sauf qu'on
ne remplace pas toutes les occurrences par une même chaîne, mais par les
éléments d'une séquence de chaînes.

Merci d'avance.


--
François

10 réponses

1 2 3
Avatar
Pierre Maurette
Francois, le 24/10/2008 a écrit :
Bonjour à tous,


J'ai une chaîne de caractères ch qui contient par exemple 20 occurrences
de la chaîne "__TRUC__". Elle en contient 20 occurrences exactement car ch a
été construite comme ça. Et j'ai une séquence seq contenant 20 chaînes, comme
par exemple :

seq = ['a0','a1',...,'a19']


Comment faire de manière la plus simple possible pour remplacer :
- la première occurrence de "__TRUC__" dans ch par 'a0'
- la deuxième occurrence de "__TRUC__" dans ch par 'a1'
.
.
.
- la vingtième occurrence de "__TRUC__" dans ch par 'a19' ?


Je sais par exemple que ch.replace("__TRUC__","xxx") remplace toutes les
occurrences de "__TRUC__" dans ch par "xxx". J'aimerais bien savoir si on
peut faire sans trop se fatiguer la même chose sauf qu'on ne remplace pas
toutes les occurrences par une même chaîne, mais par les éléments d'une
séquence de chaînes.




Je ne suis pas à l'aise avec re. Il doit y avoir des solutions
élégantes avec yield etc., mais c'est la même chose. Immédiatement,
sans penser performances, j'ai fait un truc comme ça:


#fabriquer les données pour test
seq = ['a' + str(_) for _ in range(20)]
ch = ' zorglub '.join(['Pierre Maurette'] * 21)

#traiter
s = ch.split('zorglub')
result = ''.join([s[i] + seq[i] for i in range(20)] + [s[-1]])

#afficher
print result

--
Pierre Maurette
Avatar
Pierre Maurette
(supersedes )

Francois, le 24/10/2008 a écrit :
Bonjour à tous,


J'ai une chaîne de caractères ch qui contient par exemple 20
occurrences de la chaîne "__TRUC__". Elle en contient 20 occurrences
exactement car ch a été construite comme ça. Et j'ai une séquence seq
contenant 20 chaînes, comme par exemple :

seq = ['a0','a1',...,'a19']


Comment faire de manière la plus simple possible pour remplacer :
- la première occurrence de "__TRUC__" dans ch par 'a0'
- la deuxième occurrence de "__TRUC__" dans ch par 'a1'
.
.
.
- la vingtième occurrence de "__TRUC__" dans ch par 'a19' ?


Je sais par exemple que ch.replace("__TRUC__","xxx") remplace toutes
les occurrences de "__TRUC__" dans ch par "xxx". J'aimerais bien savoir si
on peut faire sans trop se fatiguer la même chose sauf qu'on ne remplace
pas toutes les occurrences par une même chaîne, mais par les éléments d'une
séquence de chaînes.




Je ne suis pas à l'aise avec re. Il doit y avoir des solutions
élégantes avec yield etc., mais c'est la même chose. Immédiatement,
sans penser performances, j'ai fait un truc comme ça:


#fabriquer les données pour test
seq = ['a' + str(_) for _ in range(20)]
ch = ' zorglub '.join(['Pierre Maurette'] * 21)

#traiter
s = ch.split('zorglub')
result = ''.join([s[i] + seq[i] for i in range(20)] + [s[-1]])
#ou
result = ''.join([a[0] + a[1] for a in zip(s, seq)] + [s[-1]])

#afficher
print result

--
Pierre Maurette
Avatar
Francois
Pierre Maurette a écrit :

Je ne suis pas à l'aise avec re.



Moi non plus, mais une réponse avec le module re m'intéresserait
beaucoup. Ceci étant, je ne sais pas si dans mon problème ce module
aiderait beaucoup. En effet, reconnaître la sous-chaîne '__TRUC__' dans
la chaîne ch n'est pas très difficile. Au niveau expression régulière,
le motif à rechercher est plutôt simple : c'est juste '__TRUC__'. Mon
problème est vraiment au niveau de la substitution des motifs trouvés.
Je ne suis pas sûr que le module re puisse apporter un plus
significatif. Je demande à voir.

Il doit y avoir des solutions élégantes
avec yield etc.,



Ah oui, je n'y avais pas pensé à ça. Faut dire que je connais pas bien
yield mais effectivement ça doit être une bonne piste.

mais c'est la même chose. Immédiatement, sans penser
performances, j'ai fait un truc comme ça:
[couic]



Merci bien pour cet exemple qui fonctionne bien. J'avais pas pensé au
coup du split(). Pour ce qui est des performances, je m'en moque un peu,
c'est plus la lisibilité et la simplicité du code qui m'importe. De ce
point de vue, votre exemple me semble très satisfaisant.

Merci beaucoup.


--
François
Avatar
kib2
Ceci à l'air de marcher (l'initialisation des listes est à revoir):

##################################################
ch, seq = [], []

for i in xrange(20):
ch.append('__TRUC__')
seq.append('a%i'%i)

print 'ch initial est :n%s'%ch

for i,_ in enumerate(seq):
ch[i] = ch[i].replace("__TRUC__","%s"%seq[i])

print 'ch final est :n%s'%ch
Avatar
Amaury Forgeot d'Arc
Francois a écrit :
Bonjour à tous,

J'ai une chaîne de caractères ch qui contient par exemple 20
occurrences de la chaîne "__TRUC__". Elle en contient 20 occurrences
exactement car ch a été construite comme ça. Et j'ai une séquence seq
contenant 20 chaînes, comme par exemple :

seq = ['a0','a1',...,'a19']


Comment faire de manière la plus simple possible pour remplacer :
- la première occurrence de "__TRUC__" dans ch par 'a0'
- la deuxième occurrence de "__TRUC__" dans ch par 'a1'
.
.
.
- la vingtième occurrence de "__TRUC__" dans ch par 'a19' ?


Je sais par exemple que ch.replace("__TRUC__","xxx") remplace toutes
les occurrences de "__TRUC__" dans ch par "xxx". J'aimerais bien savoir
si on peut faire sans trop se fatiguer la même chose sauf qu'on ne
remplace pas toutes les occurrences par une même chaîne, mais par les
éléments d'une séquence de chaînes.



Il suffit de les remplacer un par un:
ch = ch.replace("__TRUC__", 'a0', 1)
ch = ch.replace("__TRUC__", 'a1', 1)
...
ch = ch.replace("__TRUC__", 'a19', 1)
(c'est le "1" à la fin qui indique de ne faire qu'un seul remplacement)

Dans une boucle, cela devient:

for s in seq:
ch = ch.replace("__TRUC__", s, 1)

--
Amaury
Avatar
Francois
Amaury Forgeot d'Arc a écrit :

Il suffit de les remplacer un par un:
ch = ch.replace("__TRUC__", 'a0', 1)
ch = ch.replace("__TRUC__", 'a1', 1)
...
ch = ch.replace("__TRUC__", 'a19', 1)
(c'est le "1" à la fin qui indique de ne faire qu'un seul remplacement)

Dans une boucle, cela devient:

for s in seq:
ch = ch.replace("__TRUC__", s, 1)



Parfait ! Je n'avais pas pensé à regarder la doc de replace car je ne
soupçonnais pas l'existence de ce paramètre optionnel. Merci beaucoup.

Merci à Kib2 aussi pour sa proposition.


On peut dire que mon problème est résolu, mais j'ai quand même une
question dans la continuité de tout ça. Dans les instructions

for s in seq:
ch = ch.replace("__TRUC__", s, 1)

à chaque itération, un nouvel objet chaîne est créé car les chaînes de
caractères ne sont pas modifiables en Python. On pourrait imaginer que
ça puisse être coûteux en ressource mémoire pour des grosses chaînes de
caractères (ce n'est pas le cas dans ma situation, je pose juste la
question par curiosité) . Existe t-il en Python un type/classe qui soit
comme une chaîne de caractères mais modifiable ? Pour qu'on puisse avoir
une méthode replace qui ne crée par un nouvel objet mais le modifie
uniquement ?


--
François
Avatar
Méta-MCI \(MVP\)
Salut !

reduce me semble bien adapté à ton cas :

ch = reduce(lambda a,b: a.replace("__TRUC__",b,1), seq, ch)


@-salutations
--
Michel Claveau
Avatar
Amaury Forgeot d'Arc
Francois a écrit :
On peut dire que mon problème est résolu, mais j'ai quand même une
question dans la continuité de tout ça. Dans les instructions

for s in seq:
ch = ch.replace("__TRUC__", s, 1)

à chaque itération, un nouvel objet chaîne est créé car les chaînes de
caractères ne sont pas modifiables en Python. On pourrait imaginer que
ça puisse être coûteux en ressource mémoire pour des grosses chaînes de
caractères (ce n'est pas le cas dans ma situation, je pose juste la
question par curiosité) . Existe t-il en Python un type/classe qui soit
comme une chaîne de caractères mais modifiable ? Pour qu'on puisse avoir
une méthode replace qui ne crée par un nouvel objet mais le modifie
uniquement ?



Le remplacement change la longueur du texte, et décale les caractères
qui suivent ; même si on modifie l'objet en place, cela fait des
opérations en mémoire.

Cependant il existe déjà une fonction qui fait plusieurs remplacements
en un coup, en ne créant qu'un seul objet: c'est l'opérateur %.
Ton problème peut l'utiliser, mais il faut pour cela une transformation
intermédiaire:
ch.replace("__TRUC__", "%s") % seq
Deux objets, c'est mieux que len(seq) en termes d'allocation de mémoire,
mais je ne sais pas si cela en vaut la peine : l'opérateur % est quand
même beaucoup plus lent qu'un simple replace().

--
Amaury
Avatar
Francois
Amaury Forgeot d'Arc a écrit :

Le remplacement change la longueur du texte, et décale les caractères
qui suivent ; même si on modifie l'objet en place, cela fait des
opérations en mémoire.



C'est bizarre mais dans cette phrase j'ai l'impression que tu supposes
que la chaîne est modifiée, or, selon moi, la chaîne n'est pas modifiée
et Python en crée tout simplement une nouvelle. Il me semble que la
méthode replace renvoie une nouvelle chaîne sans modifier la chaîne
initiale.

La question que je me posais c'est de savoir s'il existait une classe
prédéfinie en Python qui implémente un type de chaînes de caractères
mais modifiables.

--
François
Avatar
Amaury Forgeot d'Arc
Francois a écrit :
Amaury Forgeot d'Arc a écrit :

Le remplacement change la longueur du texte, et décale les caractères
qui suivent ; même si on modifie l'objet en place, cela fait des
opérations en mémoire.



C'est bizarre mais dans cette phrase j'ai l'impression que tu supposes
que la chaîne est modifiée, or, selon moi, la chaîne n'est pas modifiée
et Python en crée tout simplement une nouvelle. Il me semble que la
méthode replace renvoie une nouvelle chaîne sans modifier la chaîne
initiale.


>
La question que je me posais c'est de savoir s'il existait une classe
prédéfinie en Python qui implémente un type de chaînes de caractères
mais modifiables.



array.array('c'), ou depuis python 2.6: bytearray().


--
Amaury
1 2 3