Bir dizeyi her nth karakterde bölmek mümkün mü?
Örneğin, aşağıdakileri içeren bir dizem olduğunu varsayalım:
'1234567890'
Böyle görünmesini nasıl sağlayabilirim:
['12','34','56','78','90']
Bir dizeyi her nth karakterde bölmek mümkün mü?
Örneğin, aşağıdakileri içeren bir dizem olduğunu varsayalım:
'1234567890'
Böyle görünmesini nasıl sağlayabilirim:
['12','34','56','78','90']
Yanıtlar:
>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range(0, len(line), n)]
['12', '34', '56', '78', '90']
Tam olarak söylemek gerekirse, bunu normal ifadeyle yapabilirsiniz:
>>> import re
>>> re.findall('..','1234567890')
['12', '34', '56', '78', '90']
Tek sayıda karakter için bunu yapabilirsiniz:
>>> import re
>>> re.findall('..?', '123456789')
['12', '34', '56', '78', '9']
Daha uzun parçalar için normal ifadeyi basitleştirmek için aşağıdakileri de yapabilirsiniz:
>>> import re
>>> re.findall('.{1,2}', '123456789')
['12', '34', '56', '78', '9']
Ve re.finditer
dizge yığın tarafından yığın oluşturmak için uzunsa kullanabilirsiniz.
'.'*n
Daha açık hale getirmek için bile yazı yazılabilir . Birleştirme yok, sıkıştırma yok, döngü yok, liste kavraması yok; sadece sonraki iki karakteri yan yana bul, tam olarak bir insan beyni onun hakkında böyle düşünüyor. Monty Python hala hayatta olsaydı, bu yöntemi çok isterdi!
flags=re.S
.
Bunun için zaten python'da dahili bir fonksiyon var.
>>> from textwrap import wrap
>>> s = '1234567890'
>>> wrap(s, 2)
['12', '34', '56', '78', '90']
Wrap için doktora şöyle diyor:
>>> 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
dize boşluk içeriyorsa sorulmayabilir. örneğin, wrap('0 1 2 3 4 5', 2)
döndürür ['0', '1', '2', '3', '4', '5']
(elemanlar çıkarılır)
Öğeleri n-uzunluk gruplarına gruplamanın bir başka yaygın yolu:
>>> s = '1234567890'
>>> map(''.join, zip(*[iter(s)]*2))
['12', '34', '56', '78', '90']
Bu yöntem doğrudan için dokümanlardan gelir zip()
.
zip(*[iter(s)]*2)
anlamakta zorlanırsa , Python'da nasıl zip(*[iter(s)]*n)
çalışır? Başlıklı konuyu okuyun. .
>>> map(''.join, zip(*[iter('01234567')]*5))
->['01234']
zip()
ile itertools.zip_longest()
:map(''.join, zip_longest(*[iter(s)]*2, fillvalue=''))
Bu itertools sürümü daha kısa ve daha okunabilir olduğunu düşünüyorum:
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)))
PyPI'den daha fazla itertools kullanma :
>>> from more_itertools import sliced
>>> list(sliced('1234567890', 2))
['12', '34', '56', '78', '90']
Şu grouper()
tarifleri kullanabilirsiniz 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)
Bu işlevler bellek verimlidir ve yinelenebilir özelliklerle çalışır.
Aşağıdaki kodu deneyin:
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)
beklendiği gibi çalışması için kullanmanız gerekiyor: 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']
Her zamanki gibi, bir astarı sevenler için
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)
olsun this is a line split into n characters
. Daha iyi koyarak olabilir misiniz line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]
? Bunu düzeltin ve iyi bir cevap :).
,blah
ve neden gerekli? blah
Herhangi bir alfa karakteri / karakteriyle yer değiştirebileceğimi , ancak sayıları değiştiremediğimi ve blah
/ ve virgülü kaldıramayacağımı fark ettim . Editörüm şu boşlukların eklenmesini öneriyor ,
: s
enumerate
iki yineleme döndürür, bu yüzden onları koymak için iki yere ihtiyacınız vardır. Ama aslında bu durumda hiçbir şey için ikinci yinelenebilir gerekmez.
blah
çizgi veya çift alt çizgi kullanmayı tercih etmektense , bkz. Stackoverflow.com/questions/5893163/…
Kısa dize için basit bir özyinelemeli çözüm:
def split(s, n):
if len(s) < n:
return []
else:
return [s[:n]] + split(s[n:], n)
print(split('1234567890', 2))
Veya böyle bir formda:
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)
, özyinelemeli yaklaşımda tipik bölme ve fethetme desenini daha açık bir şekilde gösteren (pratik olarak bu şekilde yapılması gerekli değildir)
more_itertools.sliced
daha önce bahsedilmişti . İşte more_itertools
kütüphaneden dört seçenek daha :
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)]
İkinci seçeneklerin her biri aşağıdaki çıktıyı üretir:
['12', '34', '56', '78', '90']
Tartışılan seçenekleri için Dokümantasyon: grouper
, chunked
, windowed
,split_after
Bu basit bir döngü ile elde edilebilir.
a = '1234567890a'
result = []
for i in range(0, len(a), 2):
result.append(a[i : i + 2])
print(result)
Çıktı ['12', '34', '56', '78', '90', 'a'] gibi görünüyor