Pisahkan string setiap karakter ke-n?


Jawaban:


550
>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range(0, len(line), n)]
['12', '34', '56', '78', '90']

35
Ini adalah jawaban yang sangat hebat karena tidak berbelit-belit dan fakta itu memungkinkan Anda untuk mengingat metode ini dengan mudah karena kesederhanaannya
Trevor Rudolph

1
@TrevorRudolph Hanya melakukan persis seperti yang Anda katakan. Jawaban di atas sebenarnya hanya untuk loop tetapi diekspresikan secara python. Juga, jika Anda perlu mengingat jawaban "sederhana", ada setidaknya ratusan ribu cara untuk mengingatnya: membintangi halaman di stackoverflow; menyalin dan menempelkan ke email; menyimpan file "membantu" dengan hal-hal yang ingin Anda ingat; cukup menggunakan mesin pencari modern kapan pun Anda membutuhkan sesuatu; menggunakan bookmark di (mungkin) setiap browser web; dll
dylnmc

1
Pada meskipun kedua, tampak seolah-olah Anda adalah serius. Saya benar-benar berharap Anda serius karena itu tidak berbelit - belit.
dylnmc

1
saya serius, saya menggunakan kode ini di konverter biner saya di emulator, saya suka itu adalah pythonic untuk loop haaha tetapi terima kasih untuk lebih lanjut memecah mengapa saya menikmati metode ini!
Trevor Rudolph

5
Ironisnya, mencoba menggunakan kata-kata dengan cara yang tidak memiliki makna tersembunyi, akan sering menghasilkan kalimat yang berbelit-belit.
deed02392

208

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.finditerjika string tersebut panjang untuk menghasilkan chunk by chunk.


3
Sejauh ini, inilah jawaban terbaik di sini dan layak berada di puncak. Seseorang bahkan dapat menulis '.'*nuntuk 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!
jdk1.0

Ini adalah metode tercepat untuk string yang cukup panjang juga: gitlab.com/snippets/1908857
Ralph Bolton

Ini tidak akan berfungsi jika string berisi baris baru. Ini perlu flags=re.S.
Aran-Fey

ahhh .... regex .... kenapa aku tidak memikirkan XD itu
Tn. PizzaGuy

148

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.
'''

2
print (wrap ('12345678', 3)) membagi string menjadi kelompok-kelompok 3 digit, tetapi dimulai di depan dan bukan di belakang. Hasil: ['123', '456', '78']
Atalanttore

2
Sangat menarik untuk belajar tentang 'membungkus' namun tidak melakukan persis apa yang diminta di atas. Ini lebih berorientasi pada menampilkan teks, daripada memisahkan string ke sejumlah karakter.
Oren

2
wrapmungkin 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)
satomacoto

3
Ini memang menjawab pertanyaan, tetapi apa yang terjadi jika ada spasi dan Anda ingin mereka dipertahankan dalam karakter yang terpisah? wrap () menghilangkan spasi jika jatuh tepat setelah sekelompok karakter yang terpisah
Iron Attorney

1
Ini berfungsi buruk jika Anda ingin membagi teks dengan tanda hubung (angka yang Anda berikan sebagai argumen sebenarnya adalah jumlah MAKSIMUM karakter, bukan yang tepat, dan rusak yaitu pada tanda hubung dan spasi putih).
MrVocabulary

81

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


2
Dalam [19]: a = "hello world"; daftar (peta ("" .join, zip (* [iter (a)] * 4))) dapatkan hasilnya ['neraka', 'o wo'].
truease.com

16
Jika seseorang merasa zip(*[iter(s)]*2)sulit untuk dipahami, baca Bagaimana cara zip(*[iter(s)]*n)kerjanya di Python? .
Grijesh Chauhan

15
Ini tidak termasuk jumlah ganjil karakter, itu hanya akan menjatuhkan karakter tersebut: >>> map(''.join, zip(*[iter('01234567')]*5))->['01234']
Bjorn

3
Untuk juga menangani jumlah karakter ganjil, gantikan zip()dengan itertools.zip_longest():map(''.join, zip_longest(*[iter(s)]*2, fillvalue=''))
Paulo Freitas

Juga berguna: dokumen untukmaps()
winklerrr

58

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

7
tetapi tidak benar-benar efisien: bila diterapkan pada string: terlalu banyak salinan
Eric

1
Ini juga tidak bekerja jika seq adalah generator, yang adalah apa yang versi itertools adalah untuk . Bukan berarti OP meminta itu, tetapi tidak adil untuk mengkritik versi itertool tidak sesederhana itu.
CryingCyclops

25

Saya suka solusi ini:

s = '1234567890'
o = []
while s:
    o.append(s[:2])
    s = s[2:]

25

Menggunakan more-itertools dari PyPI:

>>> from more_itertools import sliced
>>> list(sliced('1234567890', 2))
['12', '34', '56', '78', '90']

12

Anda bisa menggunakan grouper()resep dari itertools:

Python 2.x:

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)

Python 3.x:

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.


6

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

Jawaban Anda tidak memenuhi persyaratan OP, Anda harus menggunakannya yield ''.join(piece)untuk membuatnya berfungsi seperti yang diharapkan: eval.in/813878
Paulo Freitas

5
>>> 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']

4

Coba ini:

s='1234567890'
print([s[idx:idx+2] for idx,val in enumerate(s) if idx%2 == 0])

Keluaran:

['12', '34', '56', '78', '90']

3

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

Ketika saya menjalankan ini di Python Fiddle dengan print(line)saya dapatkan this is a line split into n characterssebagai 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 :).
Apa yang ada di Google Search

Bisakah Anda menjelaskan ,blahdan mengapa itu perlu? Saya perhatikan saya dapat mengganti blahdengan karakter alfa apa pun, tetapi bukan angka, dan tidak dapat menghapus blahatau / dan koma. Editor saya menyarankan menambahkan spasi putih setelah ,: s
toonarmycaptain

enumeratemengembalikan dua iterables, jadi Anda perlu dua tempat untuk meletakkannya. Tetapi Anda sebenarnya tidak membutuhkan iterable kedua untuk apa pun dalam kasus ini.
Daniel F

1
Daripada blahsaya lebih suka menggunakan underscore atau double underscore, lihat: stackoverflow.com/questions/5893163/…
Andy Royal

2

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)


2

Saya terjebak dalam skenario yang sama.

Ini berhasil untuk saya

x="1234567890"
n=2
list=[]
for i in range(0,len(x),n):
    list.append(x[i:i+n])
print(list)

Keluaran

['12', '34', '56', '78', '90']

1

more_itertools.slicedtelah disebutkan sebelumnya. Berikut adalah empat opsi lagi dari more_itertoolsperpustakaan:

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


0

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


2
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan meningkatkan nilai jangka panjangnya.
β.εηοιτ.βε

2
Ini adalah solusi yang sama seperti di sini: stackoverflow.com/a/59091507/7851470
Georgy
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.