Ist es möglich, jedes n-te Zeichen eine Zeichenfolge zu teilen?
Angenommen, ich habe eine Zeichenfolge, die Folgendes enthält:
'1234567890'
Wie kann ich es so aussehen lassen:
['12','34','56','78','90']
Ist es möglich, jedes n-te Zeichen eine Zeichenfolge zu teilen?
Angenommen, ich habe eine Zeichenfolge, die Folgendes enthält:
'1234567890'
Wie kann ich es so aussehen lassen:
['12','34','56','78','90']
Antworten:
>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range(0, len(line), n)]
['12', '34', '56', '78', '90']
Um vollständig zu sein, können Sie dies mit einem regulären Ausdruck tun:
>>> import re
>>> re.findall('..','1234567890')
['12', '34', '56', '78', '90']
Für eine ungerade Anzahl von Zeichen können Sie dies tun:
>>> import re
>>> re.findall('..?', '123456789')
['12', '34', '56', '78', '9']
Sie können auch Folgendes tun, um den regulären Ausdruck für längere Abschnitte zu vereinfachen:
>>> import re
>>> re.findall('.{1,2}', '123456789')
['12', '34', '56', '78', '9']
Und Sie können verwenden, re.finditer
wenn die Zeichenfolge lang ist, um Chunk für Chunk zu generieren.
'.'*n
, um es klarer zu machen. Kein Beitritt, kein Zippen, keine Schleifen, kein Listenverständnis; Finden Sie einfach die nächsten zwei Zeichen nebeneinander, genau so denkt ein menschliches Gehirn darüber. Wenn Monty Python noch am Leben wäre, würde er diese Methode lieben!
flags=re.S
.
Dafür gibt es in Python bereits eine eingebaute Funktion.
>>> from textwrap import wrap
>>> s = '1234567890'
>>> wrap(s, 2)
['12', '34', '56', '78', '90']
Dies ist, was der Docstring für Wrap sagt:
>>> 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
gibt möglicherweise nicht zurück, wonach gefragt wird, wenn die Zeichenfolge Leerzeichen enthält. zB wrap('0 1 2 3 4 5', 2)
kehrt zurück ['0', '1', '2', '3', '4', '5']
(die Elemente werden entfernt)
Eine weitere gängige Methode zum Gruppieren von Elementen in Gruppen mit n Längen:
>>> s = '1234567890'
>>> map(''.join, zip(*[iter(s)]*2))
['12', '34', '56', '78', '90']
Diese Methode stammt direkt aus den Dokumenten für zip()
.
zip(*[iter(s)]*2)
Schwierigkeiten hat zu verstehen, lesen Sie Wie funktioniert es zip(*[iter(s)]*n)
in Python? .
>>> map(''.join, zip(*[iter('01234567')]*5))
->['01234']
zip()
mit itertools.zip_longest()
:map(''.join, zip_longest(*[iter(s)]*2, fillvalue=''))
Ich denke, das ist kürzer und lesbarer als die itertools-Version:
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)))
Verwenden von more-itertools von PyPI:
>>> from more_itertools import sliced
>>> list(sliced('1234567890', 2))
['12', '34', '56', '78', '90']
Sie könnten das grouper()
Rezept verwenden von 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)
Diese Funktionen sind speichereffizient und funktionieren mit allen Iterables.
Versuchen Sie den folgenden Code:
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)
, damit sie wie erwartet funktioniert
>>> 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']
Versuche dies:
s='1234567890'
print([s[idx:idx+2] for idx,val in enumerate(s) if idx%2 == 0])
Ausgabe:
['12', '34', '56', '78', '90']
Wie immer für diejenigen, die einen Liner lieben
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)
bekomme ich this is a line split into n characters
als Ausgabe. Könnten Sie besser setzen : line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]
? Repariere das und es ist eine gute Antwort :).
,blah
und warum es notwendig ist? Ich stelle fest, dass ich durch blah
alle Alpha-Zeichen, aber nicht durch Zahlen, ersetzen kann und das blah
oder / und das Komma nicht entfernen kann . Mein Redakteur schlägt vor, Leerzeichen nach dem ,
folgenden hinzuzufügen : s
enumerate
Gibt zwei Iterables zurück, sodass Sie zwei Stellen benötigen, um sie zu platzieren. In diesem Fall benötigen Sie jedoch für nichts die zweite Iterable.
blah
lieber einen Unterstrich oder einen doppelten Unterstrich zu verwenden, siehe: stackoverflow.com/questions/5893163/…
Eine einfache rekursive Lösung für kurze Zeichenfolgen:
def split(s, n):
if len(s) < n:
return []
else:
return [s[:n]] + split(s[n:], n)
print(split('1234567890', 2))
Oder in einer solchen Form:
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)
, was das typische Teilungs- und Eroberungsmuster im rekursiven Ansatz expliziter veranschaulicht (obwohl es praktisch nicht notwendig ist, dies auf diese Weise zu tun)
more_itertools.sliced
wurde bereits erwähnt . Hier sind vier weitere Optionen aus der more_itertools
Bibliothek:
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)]
Jede der letzteren Optionen erzeugt die folgende Ausgabe:
['12', '34', '56', '78', '90']
Dokumentation für diskutierten Optionen: grouper
, chunked
, windowed
,split_after
Dies kann durch eine einfache for-Schleife erreicht werden.
a = '1234567890a'
result = []
for i in range(0, len(a), 2):
result.append(a[i : i + 2])
print(result)
Die Ausgabe sieht aus wie ['12', '34', '56', '78', '90', 'a']