2011-06-25 3 views
8

Либо это ошибка, либо я собираюсь узнать что-то новое о том, как ведет себя Python. :)Ошибка в функции str.rstrip() Python или моя собственная глупость?

У меня есть словарь, заполненный парами ключ/значение. Каждый ключ имеет уникальный префикс, ias_XX_XX_. Я пытаюсь получить список каждого уникального префикса в словаре.

  1. Сначала я получаю список всех ключей, которые заканчиваются на '_x1'.
  2. Далее я снимаю '_x1' у всех из них, используя rstrip('_x1').

Это прекрасно работает для всех, кроме последнего, ias_1_1_x1. Вместо того, чтобы удаляться до ias_1_1, он становится ias_. Выполните код, чтобы увидеть для себя:

d = { 
'ias_16_10_x2':  575, 
'ias_16_10_x1':  0, 
'ias_16_10_y1':  0, 
'ias_16_10_y2':  359, 
'ias_16_9_x2':  575, 
'ias_16_9_x1':  0, 
'ias_16_9_y1':  18, 
'ias_16_9_y2':  341, 
'ias_1_1_y1':  0, 
'ias_1_1_y2':  359, 
'ias_1_1_x2':  467, 
'ias_1_1_x1':  108, 
} 

x1_key_matches = [key for key in d if '_x1' in key] 
print x1_key_matches 

unique_ids = [] 
for x1_field in x1_key_matches: 
    unique_ids.append(x1_field.rstrip('_x1')) 

print unique_ids 

Фактический выход: (Python 2.6, 2,7 и 3,2 (необходимо изменить шрифт для печати() для 3.x для работы))

['ias_16_10_x1', 'ias_16_9_x1', 'ias_1_1_x1'] 
['ias_16_10', 'ias_16_9', 'ias'] # <<<--- Why isn't this last one ias_1_1??? 

Ожидаемый результат:

['ias_16_10_x1', 'ias_16_9_x1', 'ias_1_1_x1'] 
['ias_16_10', 'ias_16_9', 'ias_1_1'] 

Если изменить имя ключа от ias_1_1 к чему-то вроде ias_1_2, или ias_1_3, сбой не возникает. Почему это происходит?

+0

В ретроспективе это могло быть более правильным и менее запутанным, если аргумент 'rstrip' был набором вместо списка. Но наборы позже были добавлены в Python. –

+2

Вы всегда можете просто срезать последние три символа: 'uids = [key [: - 3] для ключа в d, если key.endswith (" _ x1 ")]'. Обратите внимание, что 'endswith' не совпадает с тестом, который вы выполнили. – katrielalex

ответ

20

Параметр rstrip() представляет собой набор символов, которые будут лишен, а не точная строка:

>>> "abcbcbaba".rstrip("ab") 
"abcbc" 

Общая подсказка: Если вы подозреваете, что ошибку в какой-либо функции, прочитать его documentation.

+6

Ах, ха! RTFM для меня! :) –

+0

так и не понял! от имени было легко понять, как удалить «вещь» в конце. – kollery

5

С docs, подчеркивание добавлено:

символы аргумент строка, определяющая набор символов, которые будут удалены. Если опущен или None, аргумент chars по умолчанию удаляет пробелы. Аргумент chars не является суффиксом; скорее, все комбинации его значений лишены.

4

. Параметр .rstrip не является строкой, которую мы хотим разбить, это символы, которые мы хотим разбить. Убедитесь, что примеры:

>>> "12345678".rstrip("158") 
'1234567' 
>>> "12345678".rstrip("asd8qwe") 
'1234567' 
>>> "12345678".rstrip("78") 
'123456' 
>>> "1234568788".rstrip("78") 
'123456' 
2

Попробовать это вместо:

unique_ids.append(re.sub('_x1$', '', x1_field) 
+3

Спасибо. Я закончил использование 'unique_ids.append (x1_field.rsplit ('_ x1', 1) [0])'. Какие-либо преимущества для использования вашего решения регулярного выражения? –

+0

Не совсем. Возможно, преждевременная оптимизация? :) Но я не знаю, какой из них самый быстрый. –

+3

Но я должен признать, что мне больше нравится ваше решение ... и, основываясь на очень быстром тестировании, кажется, по крайней мере, в два раза быстрее, чем у одного. Примечание для себя: прекратите полагаться на регулярные выражения для всего. –

0

rstrip возвращает копию строки с трейлинг символы удаляются.

Например:

>>> ' spacious '.rstrip() 
' spacious' 
>>> "AABAA".rstrip("A") 
'AAB' 
>>> "ABBA".rstrip("AB") # both AB and BA are stripped 
'' 
>>> "ABCABBA".rstrip("AB") 
'ABC' 

######## 

>>> ' spacious '.rstrip() 
' spacious' 
>>> 'mississippi'.rstrip('ipz') 
'mississ' 

Если вы имеете дело с именами файлов быть очень осторожным,

>>> "cosmac.csv".replace(".csv") 
'cosma' 
>>> "cosmac.csv".replace(".csv", "") 
'cosmac' 

Надеется, что это помогает!