J'essaie d'implémenter un algorithme en place pour supprimer les doublons d'une chaîne en Python.
str1 = "geeksforgeeks" for i in range(len(str1)): for j in range(i+1,len(str1)-1): if str1[i] == str1[j]: //Error Line str1 = str1[0:j]+""+str1[j+1:] print str1
Dans le code ci-dessus, j'essaie de remplacer le caractère dupliqué par des espaces. Mais j'obtiens IndexError: string index out of range
à if str1 [i] == str1 [j]
. Suis-je en train de rater quelque chose ou n'est-ce pas la bonne façon?
Mon résultat attendu est: geksfor
4 Réponses :
Il est impossible de modifier les chaînes en place en Python, de la même manière qu'il est impossible de modifier les nombres en place en Python.
a = "something" b = 3 b += 1 # allocates a new integer, 4, and assigns it to b a += " else" # allocates a new string, " else", concatenates it to `a` to produce "something else" # then assigns it to a
Vous pouvez faire tout cela avec juste un ensemble et une compréhension. Pas besoin de compliquer les choses.
from collections import OrderedDict print("".join(OrderedDict.fromkeys(str1)))
"Le simple vaut mieux que le complexe."
~ Voir PEP20 p>
Bien que ce qui précède soit plus simple que votre réponse, c'est le moyen le plus performant de supprimer les doublons d'une collection la solution la plus simple serait d'utiliser:
str1 = "geeksforgeeks" seen = set() seen_add = seen.add print(''.join(s for s in str1 if not (s in seen or seen_add(s)))) #geksfor
C'est une utilisation intéressante (non évidente) du conditionnel ou
. Ce qui veut dire "Merci! Je déteste ça!"
Je suis désolé? Je ne suis pas sûr de suivre.
Il existe des solutions simples: stackoverflow.com/questions / 9841303 /…
Eh bien, tout en gardant la simplicité et la performance, je dis cette réponse est ce que je préfère. Et je dis la simplicité par rapport à la solution d'OP.
@AdamSmith - Elle a été retirée d'une une autre réponse , dont la citation a finalement été ajoutée dans le quatrième révision .
Comme déjà indiqué, str
est immuable, donc l'exigence in-place n'a aucun sens.
Si vous voulez obtenir la sortie souhaitée, je le ferais de la manière suivante:
str1 = 'geeksforgeeks' out = ''.join([i for inx,i in enumerate(str1) if str1.index(i)==inx]) print(out) #prints: geksfor
Ici, j'ai utilisé la fonction enumerate
pour obtenir une numérotation ( inx
) lettres et le fait que la méthode .index
de str
, renvoie l'index le plus bas possible de l'élément donc str1.index ('e')
pour la chaîne donnée est 1
, pas 2
, pas 9
et pas 10
.
Voici une version simplifiée de unique_everseen
de recettes itertools
.
str1 = "geeksforgeeks" new_str1 = ''.join(unique_everseen(str1)) # 'geksfor'
Vous pouvez ensuite utiliser ce générateur avec str.join
pour obtenir le résultat attendu.
from itertools import filterfalse def unique_everseen(iterable) seen = set() see _ add = seen.add for element in filterfalse(seen.__contains__, iterable): seen_add(element) yield element
i
prend la valeur de tous les indices valides destr1
. Alorsj
esti + 1
. Lorsquei
est l'indice valide le plus élevé,j
est donc hors de portée.Quelle est la valeur attendue?
@Alderven Quand i vaut 0 et j vaut 10, j'obtiens IndexError
@Alderven La sortie attendue est: geksfor
@ TigerhawkT3 quand i est 10, j est 10 et la longueur de la chaîne est 10, j
Vous modifiez la longueur de la chaîne en la parcourant, donc la plage change.
Vous ne pouvez pas effectuer de modification sur place d'une chaîne en Python. Les chaînes sont immuables.
@Jab J'essaye de faire en place, donc je ne peux pas utiliser un autre tableau.
@AdamSmith Mais c'était une question de concours.
@ Animeartistfromhell7 alors le concours est absurde. Vous ne pouvez pas modifier les chaînes sur place en Python. Arrêt complet.
@AdamSmith Alors je devrais essayer une autre langue? comme C?
@ Animeartistfromhell7 Je n'ai aucune expérience en C, donc je ne pourrais pas vous le dire, mais vous ne pouvez pas faire cela en Python. Cela brise la spécification du langage (les chaînes sont immuables)
@ Animeartistfromhell7 Vous pouvez utiliser un bytearray , qui est mutable.
"quand i est 10, j est 10" Pourquoi serait-ce le cas lorsque la boucle interne pour laquelle
j
est la variable de boucle utilise un objetrange
commençant pari + 1
?@Keith uniquement s'il utilise uniquement des chaînes ascii. Les chaînes Python sont unicode depuis Python3.