Эффективный способ в Python удалить элемент из строки через запятую - PullRequest
2 голосов
/ 20 мая 2010

Я ищу наиболее эффективный способ добавить элемент в строку через запятую, сохраняя при этом алфавитный порядок слов:

Например:

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

Кроме того, способ сделать это, но с сохранением идентификаторов:

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

Пример кода с благодарностью. Большое вам спасибо.

Ответы [ 4 ]

5 голосов
/ 20 мая 2010
1 голос
/ 20 мая 2010

В идеале, что-то вроде:

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))

будет работать. Но python не возвращает новый список из remove (), поэтому вы не можете сделать это все в одной строке, и вам нужны временные переменные и т. Д. Аналогичное решение, которое работает:

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 ])

Однако, чтобы быть как можно более точным, предполагая, что у вас нет ГАРАНТИИ, что все элементы действительны, вам необходимо убедиться, что каждый элемент соответствует ВСЕМ спецификациям, данным вам, а именно, что они имеют формат номер: идентификатор. Самый простой способ сделать это - использовать модуль re для поиска определенного формата регулярного выражения, возврата всех результатов и пропуска результатов, которые не соответствуют вашим ожиданиям. Используя преднамеренно компактный код, вы получаете достаточно короткое решение, которое делает хорошую проверку:

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)

Это также имеет преимущество обработки нескольких удалений одновременно. Поскольку формат ввода и форматы удаления очень похожи, а формат ввода содержит несколько элементов, имеет смысл, что формат удаления может также нуждаться в их поддержке - или, по крайней мере, полезно иметь такую ​​поддержку.

Обратите внимание, что выполнение этого способа (использование re для поиска) затруднит обнаружение элементов, которые НЕ проверяются; было бы просто сканировать все, что делает. Как взломщик, вы можете посчитать запятые на входе и сообщить о том, что что-то не удалось разобрать:

if items_found < (num_commas + 1):
    print warning_str

Это также предупредит насчет запятых без пробелов.

Чтобы правильно анализировать более сложные входные строки, вам нужно разбить их на отдельные токены, отслеживать входные строки и столбцы при разборе, распечатывать ошибки для чего-либо непредвиденного и, возможно, даже обрабатывать такие вещи, как возврат и построение графиков для более сложных входы, такие как исходный код. Для такого рода вещей, загляните в модуль pyparsing (который является сторонней загрузкой; он не поставляется с python).

1 голос
/ 20 мая 2010

Приведенный выше комментарий Мэтью является правильным подходом, но если вы уверены, что , (запятая с пробелом) встречаются только в качестве разделителей, то что-то подобное будет работать

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

Я бы не советовал использовать строки как списки. Они предназначены для другой цели, и следование советам Мэтью - правильная вещь.

0 голосов
/ 20 мая 2010
>>> import re
>>> re.sub("Bananas, |, Bananas$", "", "Apples, Bananas, Grapes, Oranges")
'Apples, Grapes, Oranges'

или

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

Это работает на ваших примерах, но должно быть изменено, если строки вычитания могут содержать метасимволы регулярного выражения, такие как [].*?{}\.

Это, как заметил один из комментаторов, строковая операция низкого уровня. Это может сработать, но подход, учитывающий структуру ваших данных, должен быть более надежным. Достаточно ли разделения на запятую / пробел, или вам нужна надежность модуля csv, зависит от возможных входных строк, которые вы ожидаете.

...