2010-05-20 5 views
2

Je suis à la recherche de la façon la plus efficace d'ajouter un élément à une chaîne séparée par des virgules, tout en maintenant l'ordre alphabétique des mots:manière efficace en Python pour supprimer un élément d'une chaîne séparée par des virgules

Par exemple :

string = 'Apples, Bananas, Grapes, Oranges' 
subtraction = 'Bananas' 
result = 'Apples, Grapes, Oranges' 

en outre, une façon de le faire, mais tout en maintenant les ID:

string = '1:Apples, 4:Bananas, 6:Grapes, 23:Oranges' 
subtraction = '4:Bananas' 
result = '1:Apples, 6:Grapes, 23:Oranges' 

Exemple de code est très apprécié. Merci beaucoup.

+1

Avez-vous vraiment besoin d'utiliser une chaîne de caractères comme structure de données, ou pouvez-vous avoir un dictionnaire ou un ensemble derrière les scènes et juste * imprimer * comme une chaîne séparée par des virgules? –

+0

Malheureusement, c'est une exigence :(merci cependant – ensnare

+0

Je ne peux pas voir la différence entre les deux cas que vous fournissez, peut-être que vous vouliez dire que vous vouliez conserver l'ordre alphabétique malgré que les identifiants soient en avant et non en Même si l'ordre de tri est correct pour commencer, les deux cas sont identiques – UncleZeiv

Répondre

1

Idéalement, quelque chose comme:

input_str = '1:Apples, 4:Bananas, 6:Grapes, 23:Oranges' 
removal_str = '4:Bananas' 
sep = ", " 

print sep.join(input_str.split(sep).remove(removal_str)) 

fonctionnerait. Mais python ne retourne pas la nouvelle liste de supprimer(), de sorte que vous ne pouvez pas faire cela sur une seule ligne, et ont besoin de variables temporaires, etc. Une solution similaire qui fonctionne est:

input_str = '1:Apples, 4:Bananas, 6:Grapes, 23:Oranges' 
removal_str = '4:Bananas' 
sep = ", " 

print sep.join([ i for i in input_str.split(sep) if i != removal_str ]) 

Cependant, pour soyez aussi correct que possible, en supposant que vous n'ayez pas de GARANTIE que tous les articles sont valides, vous devez vérifier que chaque article correspond à TOUTES les spécifications qui vous sont données, à savoir qu'elles sont du numéro de format: identifiant. La méthode la plus simple consiste à utiliser le module re pour rechercher un format d'expression régulière spécifique, renvoyer tous les résultats et ignorer les résultats qui ne correspondent pas à ce que vous souhaitez. En utilisant le code volontairement compact, vous obtenez une solution raisonnablement court qui fait une bonne validation:

def str_to_dictlist(inp_str): 
    import re 
    regexp = r"(?P<id>[0-9]+):(?P<name>[a-zA-Z0-9_]+)" 
    return [ x.groups() for x in re.finditer(regexp, inp_str) ] 

input_str = '1:Apples, 4:Bananas, 6:Grapes, 23:Oranges' 
subtraction_str = "4:Bananas" 
sep = ", " 

input_items = str_to_dictlist(input_str) 
removal_items = str_to_dictlist(subtraction_str) 
final_items = [ "%s:%s" % (x,y) for x,y in input_items if (x,y) not in removal_items ] 

print sep.join(final_items) 

Cela a aussi l'avantage de gérer le transfert multiples en même temps. Étant donné que le format d'entrée et le format de suppression sont si similaires et que le format d'entrée comporte plusieurs éléments, il est logique que le format de suppression doive également les prendre en charge, ou du moins qu'il est utile d'avoir ce support.Notez que le faire de cette façon (en utilisant re pour chercher) rendrait difficile la détection d'éléments qui NE valident PAS; il serait juste de numériser pour tout ce qui fait. En tant que hack, vous pouvez compter des virgules dans l'entrée et signaler un avertissement que quelque chose aurait pu échec de l'analyse:

if items_found < (num_commas + 1): 
    print warning_str 

Cela garde contre des virgules sans espaces aussi bien. Pour analyser correctement les chaînes d'entrée complexes, vous devez les décomposer en jetons individuels, suivre les lignes d'entrée et les colonnes au fur et à mesure que vous les analysez, imprimez des erreurs inattendues et manipulez des éléments tels que le backtracking et la création de graphes. entrées complexes comme le code source. Pour ce genre de choses, regardez dans le module pyparsing (qui est un téléchargement tiers, il ne vient pas avec python).

0
>>> import re 
>>> re.sub("Bananas, |, Bananas$", "", "Apples, Bananas, Grapes, Oranges") 
'Apples, Grapes, Oranges' 

ou

import re 
strng = '1:Apples, 4:Bananas, 6:Grapes, 23:Oranges' 
subtraction = '4:Bananas' 
result = re.sub(subtraction + ", |, " + subtraction, "", strng) 
print result 

Cela fonctionne sur vos exemples, mais il faudrait modifier si les chaînes de soustraction peuvent contenir des métacaractères d'expression régulière comme [].*?{}\.

Il s'agit, comme l'a noté un intervenant, d'une opération de chaîne de bas niveau. Cela pourrait fonctionner, mais une approche qui prend en compte la structure de vos données devrait être plus fiable. Que la division sur une virgule/espace soit suffisante ou que vous ayez besoin de la robustesse du module csv dépend des chaînes d'entrée possibles que vous attendez.

+0

Je ne sais pas pense que cela gère les cas où le premier/dernier élément est celui à supprimer.En d'autres termes, il ne traite pas l'entrée comme une liste de données (comme spécifié), mais comme une chaîne de bas niveau –

+0

Il a traité le premier cas Je l'ai maintenant modifié pour gérer aussi le dernier, mais je suis d'accord avec vous qu'une approche qui tient compte de la structure de niveau supérieur pourrait être préférable. * Dans la spécification, l'entrée * est * une chaîne, pas une liste. –

1

commentaire de Matthieu ci-dessus est la bonne approche, mais si vous êtes sûr que la , (suivie par des virgules par un espace) se produisent que comme séparateurs, alors quelque chose comme ça marcherait

def remove(str, element): 
    items = str.split(", ") 
    items.remove(element) 
    return ", ".join(items) 

Je n » Je recommande que vous utilisiez des chaînes comme des listes. Ils sont conçus pour un but différent et suivre les conseils de Matthew est la bonne chose à faire.

Questions connexes