10

Имеется строка из X символов, необходимо разбить её на N символов и забить значения по переменным, если в конечном значении отсеченная часть меньше, чем N, то мы её удаляем. На примере: Имеется строка London_is_the_capital_of_great_Britain. Её необходимо разбить на группы по 6 символов и каждую группу внести в отдельную строчную переменную (или в массив).

s='London_is_the_capital_of_great_Britain'
[s[x:x+6] for x in range (0, len(s), 6)]
['London', '_is_th', 'e_capi', 'tal_of', '_great', '_Brita', 'in']

Здесь видно, что последняя группа содержит менее 6 символов, значит мы ее не должны заносить в отдельную переменную, а просто отсечь.

jfs
  • 52,361
Xendler
  • 175

4 Answers4

5

В itertools-recipes приведен пример реализации функции grouper, которая принимает на вход итерируемый объект и число, обозначающее размер последовательностей, на которые будет разбит исходный объект. В основе функции лежит zip_longest - может быть заменена на встроенный zip (комментарий jfs).

def grouper(iterable, n):
    args = [iter(iterable)] * n
    return zip(*args)

s = 'London_is_the_capital_of_great_Britain'
l = [''.join(i) for i in grouper(s, 6)]
print(l)

['London', '_is_th', 'e_capi', 'tal_of', '_great', '_Brita']
user207200
  • 5,245
  • 2
    чтобы отбросить некратную часть, можно zip вместо zip_longest использовать. – jfs Sep 12 '17 at 10:20
  • да, это понятно, но потом то следует добавить эти группы в отдельные переменные – Xendler Sep 16 '17 at 03:01
  • В чём проблема? И какой в этом смысл? – user207200 Sep 17 '17 at 12:10
  • смысл в том, чтобы потом перемешивать эти группы по заданному алгоритму (шифр перестановки) – Xendler Sep 19 '17 at 10:40
  • @Xendler, в чем суть проблемы? Если число групп по N символов известно, то можно и распаковать полученный список в отдельные переменные. Но, скорее всего, это не лучший выход. Можно создать новый список с перемешанным по вашему алгоритму порядком. Если важно соответствие каждой из групп какому-то имени, то сразу создавать словарь. – user207200 Sep 19 '17 at 11:00
5

Чтобы выбросить группу, которая меньше по длине, в конце списка:

n = 6    
chunks = [s[i - n:i] for i in range(n, len(s) + 1, n)]

Ещё (из @slippyk комментария):

chunks = [s[i:i + n] for i in range(0, len(s) - (len(s) % n), n)]

Более наглядно предел для i можно записать как: n * (len(s) // n)— выражение делает длину s как будто кратной n.

Если список не нужен:

chunks = map(''.join, zip(*[iter(s)] * n))

Первый вариант более читаем. Последний вариант работает не только для последовательностей. zip() автоматически не кратный остаток выкидывает. Вот объяснение, что zip(*[iterator]*n) делает.

Пример:

>>> s = 'London_is_the_capital_of_great_Britain'
>>> print(*map(''.join, zip(*[iter(s)] * 6)), sep=' | ')
London | _is_th | e_capi | tal_of | _great | _Brita
jfs
  • 52,361
2

такой вариант работает и в python2 и в python3:

import re
s = 'London_is_the_capital_of_great_Britain'
n = 6
print(re.findall('.{%s}' % n, s))

результат:

['London', '_is_th', 'e_capi', 'tal_of', '_great', '_Brita']
0

aleksandr-barakin

Спасибо! Интересный и лаконичный способ.

Но можно немножко улучшить регулярку:

print(re.findall('(.{%s}|.+$)' % n, s))

тогда будет выдаваться и последняя неполная часть:

['London', '_is_th', 'e_capi', 'tal_of', '_great', '_Brita', 'in']