Apakah mungkin untuk membagi string setiap karakter ke-n?
Misalnya, saya memiliki string yang berisi yang berikut ini:
'1234567890'
Bagaimana saya bisa membuatnya terlihat seperti ini:
['12','34','56','78','90']
Apakah mungkin untuk membagi string setiap karakter ke-n?
Misalnya, saya memiliki string yang berisi yang berikut ini:
'1234567890'
Bagaimana saya bisa membuatnya terlihat seperti ini:
['12','34','56','78','90']
Jawaban:
>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range(0, len(line), n)]
['12', '34', '56', '78', '90']
Agar lengkap, Anda bisa melakukan ini dengan regex:
>>> import re
>>> re.findall('..','1234567890')
['12', '34', '56', '78', '90']
Untuk jumlah karakter ganjil, Anda dapat melakukan ini:
>>> import re
>>> re.findall('..?', '123456789')
['12', '34', '56', '78', '9']
Anda juga dapat melakukan hal berikut, untuk menyederhanakan regex untuk potongan yang lebih lama:
>>> import re
>>> re.findall('.{1,2}', '123456789')
['12', '34', '56', '78', '9']
Dan Anda dapat menggunakan re.finditer
jika string tersebut panjang untuk menghasilkan chunk by chunk.
'.'*n
untuk membuatnya lebih jelas. Tidak ada yang bergabung, tidak ada zip, tidak ada loop, tidak ada pemahaman daftar; temukan saja dua karakter berikutnya di sebelah satu sama lain, yang persis bagaimana otak manusia memikirkannya. Jika Monty Python masih hidup, dia akan menyukai metode ini!
flags=re.S
.
Sudah ada fungsi inbuilt di python untuk ini.
>>> from textwrap import wrap
>>> s = '1234567890'
>>> wrap(s, 2)
['12', '34', '56', '78', '90']
Ini adalah apa yang dikatakan docstring untuk wrap:
>>> help(wrap)
'''
Help on function wrap in module textwrap:
wrap(text, width=70, **kwargs)
Wrap a single paragraph of text, returning a list of wrapped lines.
Reformat the single paragraph in 'text' so it fits in lines of no
more than 'width' columns, and return a list of wrapped lines. By
default, tabs in 'text' are expanded with string.expandtabs(), and
all other whitespace characters (including newline) are converted to
space. See TextWrapper class for available keyword args to customize
wrapping behaviour.
'''
wrap
mungkin tidak mengembalikan apa yang diminta jika string berisi ruang. misalnya wrap('0 1 2 3 4 5', 2)
pengembalian ['0', '1', '2', '3', '4', '5']
(elemen dilucuti)
Cara umum lainnya untuk mengelompokkan elemen ke dalam grup n-length:
>>> s = '1234567890'
>>> map(''.join, zip(*[iter(s)]*2))
['12', '34', '56', '78', '90']
Metode ini datang langsung dari dokumen untuk zip()
.
zip(*[iter(s)]*2)
sulit untuk dipahami, baca Bagaimana cara zip(*[iter(s)]*n)
kerjanya di Python? .
>>> map(''.join, zip(*[iter('01234567')]*5))
->['01234']
zip()
dengan itertools.zip_longest()
:map(''.join, zip_longest(*[iter(s)]*2, fillvalue=''))
Saya pikir ini lebih pendek dan lebih mudah dibaca daripada versi itertools:
def split_by_n(seq, n):
'''A generator to divide a sequence into chunks of n units.'''
while seq:
yield seq[:n]
seq = seq[n:]
print(list(split_by_n('1234567890', 2)))
Menggunakan more-itertools dari PyPI:
>>> from more_itertools import sliced
>>> list(sliced('1234567890', 2))
['12', '34', '56', '78', '90']
Anda bisa menggunakan grouper()
resep dari itertools
:
from itertools import izip_longest
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
from itertools import zip_longest
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
Fungsi-fungsi ini hemat memori dan berfungsi dengan semua iterables.
Coba kode berikut:
from itertools import islice
def split_every(n, iterable):
i = iter(iterable)
piece = list(islice(i, n))
while piece:
yield piece
piece = list(islice(i, n))
s = '1234567890'
print list(split_every(2, list(s)))
yield ''.join(piece)
untuk membuatnya berfungsi seperti yang diharapkan: eval.in/813878
>>> from functools import reduce
>>> from operator import add
>>> from itertools import izip
>>> x = iter('1234567890')
>>> [reduce(add, tup) for tup in izip(x, x)]
['12', '34', '56', '78', '90']
>>> x = iter('1234567890')
>>> [reduce(add, tup) for tup in izip(x, x, x)]
['123', '456', '789']
Seperti biasa, untuk mereka yang suka one liners
n = 2
line = "this is a line split into n characters"
line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]
print(line)
saya dapatkan this is a line split into n characters
sebagai output. Mungkin Anda lebih baik menempatkan: line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]
? Perbaiki ini dan ini jawaban yang bagus :).
,blah
dan mengapa itu perlu? Saya perhatikan saya dapat mengganti blah
dengan karakter alfa apa pun, tetapi bukan angka, dan tidak dapat menghapus blah
atau / dan koma. Editor saya menyarankan menambahkan spasi putih setelah ,
: s
enumerate
mengembalikan dua iterables, jadi Anda perlu dua tempat untuk meletakkannya. Tetapi Anda sebenarnya tidak membutuhkan iterable kedua untuk apa pun dalam kasus ini.
blah
saya lebih suka menggunakan underscore atau double underscore, lihat: stackoverflow.com/questions/5893163/…
Solusi rekursif sederhana untuk string pendek:
def split(s, n):
if len(s) < n:
return []
else:
return [s[:n]] + split(s[n:], n)
print(split('1234567890', 2))
Atau dalam bentuk seperti itu:
def split(s, n):
if len(s) < n:
return []
elif len(s) == n:
return [s]
else:
return split(s[:n], n) + split(s[n:], n)
, yang menggambarkan pola pembagian dan penaklukan yang khas dalam pendekatan rekursif secara lebih eksplisit (meskipun secara praktis tidak perlu dilakukan dengan cara ini)
more_itertools.sliced
telah disebutkan sebelumnya. Berikut adalah empat opsi lagi dari more_itertools
perpustakaan:
s = "1234567890"
["".join(c) for c in mit.grouper(2, s)]
["".join(c) for c in mit.chunked(s, 2)]
["".join(c) for c in mit.windowed(s, 2, step=2)]
["".join(c) for c in mit.split_after(s, lambda x: int(x) % 2 == 0)]
Masing-masing opsi terakhir menghasilkan output berikut:
['12', '34', '56', '78', '90']
Dokumentasi untuk opsi yang dibahas: grouper
, chunked
, windowed
,split_after
Ini dapat dicapai dengan loop sederhana.
a = '1234567890a'
result = []
for i in range(0, len(a), 2):
result.append(a[i : i + 2])
print(result)
Outputnya terlihat seperti ['12', '34', '56', '78', '90', 'a']