Zeichenfolge jedes n-te Zeichen teilen?

381

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']
Brandon L Burnett
quelle

Antworten:

550
>>> line = '1234567890'
>>> n = 2
>>> [line[i:i+n] for i in range(0, len(line), n)]
['12', '34', '56', '78', '90']
satomacoto
quelle
35
Dies ist eine wirklich gute Antwort, da sie in keiner Weise verwickelt ist und Sie sich aufgrund ihrer Einfachheit leicht an die Methode erinnern können
Trevor Rudolph
1
@ TrevorRudolph Es macht nur genau das, was Sie es sagen. Die obige Antwort ist eigentlich nur eine for-Schleife, wird aber pythonisch ausgedrückt. Wenn Sie sich an eine "vereinfachte" Antwort erinnern müssen, gibt es mindestens Hunderttausende von Möglichkeiten, sich diese zu merken: Markieren der Seite im Stapelüberlauf; Kopieren und anschließendes Einfügen in eine E-Mail; Führen Sie eine "hilfreiche" Datei mit Dingen, an die Sie sich erinnern möchten. Verwenden Sie einfach eine moderne Suchmaschine, wann immer Sie etwas benötigen. Verwenden von Lesezeichen in (wahrscheinlich) jedem Webbrowser; usw.
dylnmc
1
Auf der zweiten Seite scheint es, als ob Sie es ernst meinen. Ich hoffe wirklich, dass Sie es ernst meinen, da es wirklich nicht verwickelt ist.
dylnmc
1
Ich meinte es ernst, ich habe diesen Code in meinem Binärkonverter in einem Emulator verwendet. Ich mochte, dass es eine Python für Loop war, haaha, aber danke, dass du weiter aufgeschlüsselt hast, warum ich die Methode mag!
Trevor Rudolph
5
Ironischerweise führt der Versuch, Wörter auf eine Weise zu verwenden, die keine versteckte Bedeutung hat, oft zu verschlungenen Sätzen.
Urkunde 02392
208

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.finditerwenn die Zeichenfolge lang ist, um Chunk für Chunk zu generieren.

der Wolf
quelle
3
Dies ist bei weitem die beste Antwort hier und verdient es, an der Spitze zu stehen. Man könnte sogar schreiben '.'*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!
JDK1.0
Dies ist die schnellste Methode auch für relativ lange Zeichenfolgen: gitlab.com/snippets/1908857
Ralph Bolton
Dies funktioniert nicht, wenn die Zeichenfolge Zeilenumbrüche enthält. Das braucht flags=re.S.
Aran-Fey
ahhh .... regex .... warum habe ich nicht an diesen XD
gedacht
148

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.
'''
Diptangsu Goswami
quelle
2
print (wrap ('12345678', 3)) teilt die Zeichenfolge in dreistellige Gruppen auf, beginnt jedoch vorne und nicht hinten. Ergebnis: ['123', '456', '78']
Atalanttore
2
Es ist interessant, etwas über "Wrap" zu lernen, aber es macht nicht genau das, was oben gefragt wurde. Es ist eher auf die Anzeige von Text ausgerichtet, als dass eine Zeichenfolge auf eine feste Anzahl von Zeichen aufgeteilt wird.
Oren
2
wrapgibt 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)
satomacoto
3
Dies beantwortet zwar die Frage, aber was passiert, wenn Leerzeichen vorhanden sind und Sie möchten, dass sie in den geteilten Zeichen beibehalten werden? wrap () entfernt Leerzeichen, wenn sie direkt nach einer geteilten Gruppe von Charakteren fallen
Iron Attorney
1
Dies funktioniert schlecht, wenn Sie Text mit Bindestrichen teilen möchten (die Zahl, die Sie als Argument angeben, ist tatsächlich die MAXIMALE Anzahl von Zeichen, nicht die exakte, und es wird unterbrochen, dh bei Bindestrichen und Leerzeichen).
MrVocabulary
81

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

Andrew Clark
quelle
2
In [19]: a = "Hallo Welt"; list (map ("" .join, zip (* [iter (a)] * 4))) erhält das Ergebnis ['hell', 'o wo'].
truease.com
16
Wenn jemand zip(*[iter(s)]*2)Schwierigkeiten hat zu verstehen, lesen Sie Wie funktioniert es zip(*[iter(s)]*n)in Python? .
Grijesh Chauhan
15
Dies erklärt nicht eine ungerade Anzahl von Zeichen, es wird einfach diese Zeichen fallen lassen: >>> map(''.join, zip(*[iter('01234567')]*5))->['01234']
Björn
3
Um auch ungerade Anzahl von Zeichen Griff ersetzen Sie einfach zip()mit itertools.zip_longest():map(''.join, zip_longest(*[iter(s)]*2, fillvalue=''))
Paulo Freitas
Ebenfalls nützlich: Dokumente fürmaps()
winklerrr
58

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)))
Russell Borogove
quelle
7
aber nicht wirklich effizient: bei Anwendung auf Strings: zu viele Kopien
Eric
1
Es funktioniert auch nicht , wenn f ein Generator ist, das ist , was die itertools Version ist für . Nicht dass OP danach gefragt hätte, aber es ist nicht fair zu kritisieren, dass die Version von itertool nicht so einfach ist.
CryingCyclops
25

Ich mag diese Lösung:

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

Verwenden von more-itertools von PyPI:

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

Sie könnten das grouper()Rezept verwenden von 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)

Diese Funktionen sind speichereffizient und funktionieren mit allen Iterables.

Eugene Yarmash
quelle
6

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)))
enderskill
quelle
Ihre Antwort entspricht nicht den Anforderungen von OP. Sie müssen sie verwenden yield ''.join(piece), damit sie wie erwartet funktioniert
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']
ben w
quelle
4

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']
U10-Vorwärts
quelle
3

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])]
Sqripter
quelle
Wenn ich dies in Python Fiddle mit einem ausführe, print(line)bekomme ich this is a line split into n charactersals 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 :).
Was ist in einer Google-Suche
Können Sie das erklären ,blahund warum es notwendig ist? Ich stelle fest, dass ich durch blahalle Alpha-Zeichen, aber nicht durch Zahlen, ersetzen kann und das blahoder / und das Komma nicht entfernen kann . Mein Redakteur schlägt vor, Leerzeichen nach dem ,folgenden hinzuzufügen : s
toonarmycaptain
enumerateGibt 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.
Daniel F
1
Anstatt blahlieber einen Unterstrich oder einen doppelten Unterstrich zu verwenden, siehe: stackoverflow.com/questions/5893163/…
Andy Royal
2

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)

englealuze
quelle
2

Ich steckte im selben Szenario fest.

Das hat bei mir funktioniert

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

Ausgabe

['12', '34', '56', '78', '90']
Strick
quelle
1

more_itertools.slicedwurde bereits erwähnt . Hier sind vier weitere Optionen aus der more_itertoolsBibliothek:

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

Pylang
quelle
0

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

Kasem007
quelle
2
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
β.εηοιτ.βε
2
Dies ist die gleiche Lösung wie hier: stackoverflow.com/a/59091507/7851470
Georgy