2013-12-11 2 views
0

Я пытаюсь найти простой способ добавить точку . к каждой цифре 3 в виде строки ('43434' -> '43.434), и я нашел интересное применение присоединиться к этой задаче:Python .join() итерация строка

num = '1234567' 
new_num = '.'.join(num[i:i+3] for i in range(0, len(num), 3)) 
# new_num = 123.456.7' 

Ну его близко к тому, что я хочу. Это то, что я хочу:

(its need to be `'1.234.567'`) 

Почему это так работает? Когда я использую нарезку на соединение, он добавляет дополнение для каждого элемента:

num = '2333' 
>>> '.'.join(num[0:2]) 
<<< '2.3' 
>>> '.'.join(num[0:3]) 
<<< '2.3.3' 

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

+0

'num [i: i + 3] для i в диапазоне (0, len (num), 3)' - Это [выражение генератора] (http://www.python.org/dev/peps/ PEP-0289 /). Быстрый поиск в Google не показывал хороших новинок для генераторов, поэтому я связал PEP с предложением их введения в язык. – user2357112

ответ

4

Ваш первый пример кода подбирает 3 цифры за время и присоединяется к ним.Ломать его

>>>num = '1234567' 
>>>x=[num[i:i+3] for i in range(0, len(num), 3)] 
>>>x 
['123', '456', '7'] 
>>>'.'.join(x) 
'123.456.7' 

num[i:i+3] часть называется нарезка и объяснил here.

В то время как во второй части вы используете join function для подключения деталей снова.

>>>num = '2333' 
>>>num[0:2] 
23 
>>>'.'.join('23') 
2.3 

Что вы хотите 1.234.567, то есть вы хотите, чтобы начать отсчет трех цифр от конца строки. Один из способов - изменить строку, сделать то, что вы делаете, и изменить результат.

>>> num = '1234567' 
>>> num[::-1] 
'7654321' 
>>> '.'.join(num[::-1][i:i+3] for i in range(0, len(num), 3))[::-1] 
'1.234.567' 
+0

Вау! Я могу использовать срез дважды? я сделал '.... join (num [i: i-3: -1] для i в диапазоне (-1, - (len (num)) - 1, -3))', а затем снова отменил его. –

+1

'num [:: - 1]' возвращает строку, которую вы затем нарезаете. поэтому 'num [:: - 1] [i: i + 3]' равно 'x = num [:: - 1]; х [я: я + 3] '. Ваш способ по существу делает то же самое, поскольку вы используете отрицательные индексы в Python. – RedBaron

+0

Я не видел генератора там. хотя «join» каким-то образом знает, как прыгать между строкой. –

1

Грубо говоря, то, что итератор это то, за что этот код будет работать:

for x in some_iterable_here: 
    print(x) 

Идея заключается в том, что итератор представляет собой последовательность значений. Списки являются итерабельными. Если some_iterable_here был представлен в списке [1, 23, -7, 'hello'], код выше распечатывал бы номер 1, 23, -7 и, наконец, строку 'hello'.

Строка - это один из вариантов итерации - это последовательность символов. Поэтому, если вы положите строку 'hello' на номер some_iterable_here, она будет распечатывать каждую букву отдельно: 'h', 'e', 'l', 'l', а затем, наконец, 'o'.

Что join делает это принять каждый элемент итератора, содержащие строки (например, список строк, как ['one', 'two', 'three'], или просто строку 'four', которая представляет собой итерация, содержащая строки 'f', 'o', 'u' и 'r') и верните новую строку, которая объединяет все строки, с чем-то между ними.

Итак, когда вы получаете кусочек num[0:3], это строка '233'. Python объединяет каждого персонажа с периодом между ними, когда вы делаете '.'.join, и вот как вы получаете '2.3.3'.

2

Если попробовать:

>>> a = (num[i:i+3] for i in range(0, len(num), 3)) 
>>> a 
<generator object <genexpr> at 0x028C2B48> 

Таким образом, первый один, по существу, с использованием:

new_num = '.'.join(a) # iterating with generator 

В качестве альтернативы, вы можете сделать с list:

new_num = '.'.join([num[i:i+3] for i in range(0, len(num), 3)]) 
# iterating with list ['123', '456', '7'] 

Это объясняет свой код, ну, так как вы можете видеть string как list:

'.'.join(num[0:3]) # num[0:3] -> '233' string -> ['2', '3', '3'] 
1

Попробуйте это решение

(".".join([num[::-1][i:i+3] for i in range(0, len(num), 3)]))[::-1] 
+2

круглые скобки дополнительно. Он работает '.... Join ([num [:: - 1] [i: i + 3] для i в диапазоне (0, len (num), 3)]) [:: - 1] -> '1.234 .567'' –

1

Если я вас понимаю:

In [15]: num = '1234567' 
#Reverse string with [::-1] 
In [16]: new_num = '.'.join(num[::-1][i:i+3] for i in range(0, len(num), 3)) 
#Repeat reverse for correct result 
In [17]: new_num = new_num[::-1] 
In [18]: print new_num 
1.234.567 
3

Возможный путь,

>>> num = '1234567' 
>>> '.'.join([num[i-3 if i-3 > 0 else 0:i] for i in range(len(num),-1,-3)][::-1]) 
'1.234.567' 

Ориентиром,

$ python -mtimeit -s'num="1234567"' '".".join(num[::-1][i:i+3] for i in range(0, len(num), 3))[::-1]' 
100000 loops, best of 3: 4.15 usec per loop 

$ python -mtimeit -s'num="1234567"' '".".join([num[i-3 if i-3 > 0 else 0:i] for i in range(len(num), -1, -3)][::-1])' 
1000000 loops, best of 3: 1.87 usec per loop 

Ни один из них не отличается ясностью для меня, но если вы предпочитаете первое (популярное решение опубликовано), оно только немного медленнее.

+0

Как насчет 'max (i-3, 0)' вместо неудобного 'if'? Кажется немного медленнее, чем ваш 'if', хотя, по крайней мере, на моей машине. – Alfe

Смежные вопросы