3
votes

Remplacer la sous-chaîne dans une chaîne à l'aide d'une liste

Je cherche un moyen plus pythonique de remplacer une longueur connue d'espaces réservés dans une chaîne par les valeurs trouvées dans une liste. Ils doivent être remplacés dans l'ordre et être utilisés une seule fois. Par exemple avec les valeurs:

for i in range(len(replaceVals)):
   origStr = origStr.replace('?', replaceVals[i], 1)

Je cherche à obtenir:

newStr = 'I went to the foo to get bar'

J'ai pu obtenir le résultat souhaité avec la boucle suivante , mais je pense qu'il devrait y avoir une meilleure façon de procéder que d'utiliser une boucle comme celle-ci.

replaceVals = ['foo', 'bar']

origStr = 'I went to the ? to get ?'


12 commentaires

origStr = 'Je suis allé au {} pour obtenir {}'. format (* replaceVals)


Cela doit être une dupe, mais le plus proche que je puisse trouver est stackoverflow.com/questions/4450592/... et il manque l'utilisation la plus basique


Copie possible de Utilisation du formatage de chaîne Python avec des listes


Les gens obtiennent-ils des points pour essayer de signaler les doublons? Juste curieux. Semble être un réel désir de la fin de ne rien permettre près d'un duplicata. Je ne veux certainement pas que SO soit rempli exactement de la même question 100 fois, mais cela ne me dérange pas 3 ou 4 de questions assez similaires, simplement parce que cela aide d'autres personnes ayant des problèmes similaires à mieux trianguler les leurs.


@TravisGriggs non, mais quel est l'intérêt d'avoir des informations reformatées en 3 ou 4 lignes (ce qui devient typique - «vous pouvez essayer ceci: ») quand il y a une seule source d'informations définitives?


@TravisGriggs ... un exemple typique


Je suppose que je ne vois pas @roganjosh. Comme pour le codage, je réduis / combine / refactorise les modèles communs, une fois qu'ils ont mûri et je peux prouver qu'ils le sont vraiment. Prématuré "on dirait que ça va être ça" avant qu'il ne mûrisse, ça ne marche pas pour moi.


@TravisGriggs Ce que je suggère, c'est que la réponse n'offre aucune explication sur les raisons pour lesquelles vous devriez utiliser la méthode proposée. Le duplicata sert son objectif en dirigeant différents termes de recherche vers une source particulière qui, je pense, fournit un contexte pour les futurs téléspectateurs. Nous pouvons être en désaccord sur ce point, très bien, mais cela s'est déroulé exactement comme je l'ai dit: "Voici un moyen de le faire"


J'aime votre réponse, juste été brûlé trop de fois sur SO ces derniers temps où je poste une question et quelqu'un gifle le "ressemble à des gens en double" et tue souvent la chance que quiconque la regarde plus loin. Le "non, je suis allé le regarder et laissez-moi clarifier pourquoi mon cas est différent" finit par arriver trop tard.


@roganjosh Cette solution ne fonctionnera que si origStr ne contient pas de {} littéral, auquel cas des étapes supplémentaires sont nécessaires pour l'échapper.


@TravisGriggs, peut-être que SO peut avoir 3 types de dups: 1 . dups exact facile à trouver, devrait être déclassé et fermé; 2 . des dups exacts difficiles à trouver, devraient être juste fermés avec un lien de référence sans pénalité à OP, certains d'entre nous viennent à SO parce que nous manquons de certaines connaissances, et en raison du manque de ces mêmes connaissances, nous ne pouvions pas reconnaître nos questions étaient des dups .; 3 . des questions similaires, qui méritent encore d'être discutées avec des liens de référence vers des questions similaires en dessous, le pensent comme des enseignants donnant aux élèves des problèmes de légères variations mais testant le même concept.


Fonctionne pour moi @Indomimus


5 Réponses :


2
votes

Voici une idée utilisant des generators:

replaceVals = iter(['foo', 'bar', 'other'])
origStr = 'I went to the ? to get ?'

(' ').join(next(replaceVals) if i == '?' else i for i in origStr.split())
#'I went to the foo to get bar'

Output:

'I went to the foo to get bar'

L'avantage de le faire de cette façon, est que la quantité d'éléments dans replaceVals ne doit pas nécessairement correspondre à la quantité d'éléments à remplacer dans origStr :

replaceVals = iter(['foo', 'bar'])
origStr = 'I went to the ? to get ?'

(' ').join(next(replaceVals) if i == '?' else i for i in origStr.split())

Cependant, l'utilisation d'un formatage de chaîne entraînerait des erreurs dans ces circonstances.


0 commentaires

0
votes

f chaîne

r=["foo","bar"]
origStr = f'I went to the {r[0]} to get {r[1]}'

origStr
Out[21]: 'I went to the foo to get bar'


0 commentaires

1
votes

La réponse de @roganjosh dans les commentaires est peut-être la meilleure, bien que l'OP soit suffisamment abstrait pour que son cas réel ne soit pas clair. J'étais curieux de savoir si on pouvait faire cela avec des f-strings qui apparaissaient dans Python3. Ce qui rend une f-string moins attrayante que celle de @ roganjosh, c'est qu'il est tellement facile de décompresser la séquence de remplacement via l'appel .format () . Cela dit, SI vous vouliez essayer une chaîne de caractères, quelque chose comme ceci fonctionnerait:

replaceVals = ['foo', 'bar'] 
stream = iter(replaceVals)
f'I went to the {stream.next()} to get {stream.next()}'


0 commentaires

0
votes

Vous pouvez diviser la chaîne avec '?' , puis utiliser itertools.zip_longest pour associer des sous-chaînes dans la liste résultante avec des chaînes de remplacement dans replaceVals code > avec une chaîne vide comme valeur de remplissage, et joignez les paires de chaînes après les avoir aplaties avec une expression de générateur:

from itertools import zip_longest
''.join(i for p in zip_longest(origStr.split('?'), replaceVals, fillvalue='') for i in p)


0 commentaires

2
votes

Vous pouvez utiliser les méthodes replace et format de la chaîne comme indiqué ci-dessous:

origStr.replace('?','{}').format(*replaceVals)

Out[334]: 'I went to the foo to get bar'


0 commentaires