Dividi la stringa all'ennesimo carattere?


Risposte:


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

35
Questa è una risposta davvero fantastica perché non è contorta in alcun modo e questo fatto ti consente di ricordare facilmente il metodo grazie alla sua semplicità
Trevor Rudolph,

1
@TrevorRudolph Fa esattamente solo quello che dici. La risposta di cui sopra è in realtà solo un ciclo for ma espressa in modo sintetico. Inoltre, se hai bisogno di ricordare una risposta "semplicistica", ci sono almeno centinaia di migliaia di modi per ricordarli: con protagonista la pagina su StackOverflow; copia e incolla in una e-mail; mantenendo un file "utile" con cose che vuoi ricordare; semplicemente usando un moderno motore di ricerca ogni volta che hai bisogno di qualcosa; usare i segnalibri in (probabilmente) ogni browser web; ecc.
dylnmc,

1
Al secondo però, sembra che tu sia serio. Spero davvero che tu sia serio dal momento che non è davvero contorto.
dylnmc,

1
ero serio, ho usato questo codice nel mio convertitore binario in un emulatore, mi è piaciuto che fosse un pitone per loop haaha ma grazie per aver analizzato ulteriormente perché mi piace il metodo!
Trevor Rudolph,

5
Ironia della sorte, tentando di usare le parole in un modo che non avrà un significato nascosto, si tradurrà spesso in frasi contorte.
deed02392,

208

Solo per essere completo, puoi farlo con una regex:

>>> import re
>>> re.findall('..','1234567890')
['12', '34', '56', '78', '90']

Per un numero dispari di caratteri puoi farlo:

>>> import re
>>> re.findall('..?', '123456789')
['12', '34', '56', '78', '9']

Puoi anche fare quanto segue, per semplificare la regex per blocchi più lunghi:

>>> import re
>>> re.findall('.{1,2}', '123456789')
['12', '34', '56', '78', '9']

E puoi usare re.finditerse la stringa è lunga per generare un blocco per blocco.


3
Questa è di gran lunga la migliore risposta qui e merita di essere al top. Si potrebbe anche scrivere '.'*nper renderlo più chiaro. Nessun join, nessun zipping, nessun loop, nessuna comprensione dell'elenco; trova i due personaggi seguenti uno accanto all'altro, ed è esattamente come un cervello umano ci pensa. Se Monty Python fosse ancora vivo, adorerebbe questo metodo!
jdk1.0,

Questo è il metodo più veloce anche per stringhe abbastanza lunghe: gitlab.com/snippets/1908857
Ralph Bolton

Questo non funzionerà se la stringa contiene newline. Questo ha bisogno flags=re.S.
Aran-Fey,

ahhh .... regex .... perché non ho pensato a
quell'XD

148

Per questo c'è già una funzione integrata in Python.

>>> from textwrap import wrap
>>> s = '1234567890'
>>> wrap(s, 2)
['12', '34', '56', '78', '90']

Questo è ciò che dice la documentazione per avvolgere:

>>> 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)) divide la stringa in gruppi di 3 cifre, ma inizia davanti e non dietro. Risultato: ['123', '456', '78']
Atalanttore

2
È interessante conoscere "avvolgere", ma non sta facendo esattamente ciò che è stato chiesto sopra. È più orientato alla visualizzazione del testo, piuttosto che suddividere una stringa in un numero fisso di caratteri.
Oren,

2
wrappotrebbe non restituire ciò che viene richiesto se la stringa contiene spazio. es. wrap('0 1 2 3 4 5', 2)ritorni ['0', '1', '2', '3', '4', '5'](gli elementi sono spogliati)
satomacoto

3
Questo in effetti risponde alla domanda, ma cosa succede se ci sono spazi e li vuoi mantenere nei personaggi divisi? wrap () rimuove gli spazi se cadono subito dopo una divisione di personaggi
Iron Attorney

1
Questo funziona male se vuoi dividere il testo con trattini (il numero che dai come argomento è in realtà il MASSIMO numero di caratteri, non uno esatto, e si rompe cioè su trattini e spazi bianchi).
Mr Vocabolario,

81

Un altro modo comune di raggruppare gli elementi in gruppi di lunghezza n:

>>> s = '1234567890'
>>> map(''.join, zip(*[iter(s)]*2))
['12', '34', '56', '78', '90']

Questo metodo deriva direttamente dalla documentazione di zip().


2
In [19]: a = "ciao mondo"; list (map ("" .join, zip (* [iter (a)] * 4))) ottiene il risultato ['hell', 'o wo'].
truease.com,

16
Se qualcuno trova zip(*[iter(s)]*2)difficile da capire, leggi Come zip(*[iter(s)]*n)funziona in Python? .
Grijesh Chauhan,

15
Questo non tiene conto di un numero dispari di caratteri, semplicemente lascerà cadere quei caratteri: >>> map(''.join, zip(*[iter('01234567')]*5))->['01234']
Bjorn

3
Per gestire anche il numero dispari di caratteri basta sostituire zip()con itertools.zip_longest():map(''.join, zip_longest(*[iter(s)]*2, fillvalue=''))
Paulo Freitas l'

Utile anche: documenti permaps()
winklerrr

58

Penso che questo sia più breve e più leggibile rispetto alla versione 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
ma non molto efficiente: se applicato alle stringhe: troppe copie
Eric

1
Inoltre non funziona se ss è un generatore, che è ciò che la versione itertools è per . Non è stato richiesto dall'OP, ma non è giusto criticare la versione di itertool non essendo così semplice.
CryingCyclops,

25

Mi piace questa soluzione:

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

25

Utilizzando more-itertools da PyPI:

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

12

Puoi usare la grouper()ricetta da 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)

Queste funzioni sono efficienti in termini di memoria e funzionano con tutti gli iterabili.


6

Prova il seguente codice:

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

La tua risposta non soddisfa i requisiti di OP, devi usarla yield ''.join(piece)per farlo funzionare come previsto: 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

Prova questo:

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

Produzione:

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

3

Come sempre, per chi ama una fodera

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

Quando eseguo questo in Python Fiddle con un print(line)ottengo this is a line split into n characterscome output. Potresti stare meglio mettendo line = [line[i * n:i * n+n] for i,blah in enumerate(line[::n])]:? Risolvi questo problema ed è una buona risposta :).
Cosa c'è in una ricerca su Google

Puoi spiegare il ,blahe perché è necessario? Ho notato che posso sostituire blahcon qualsiasi carattere / i alfa, ma non numeri, e non posso rimuovere blaho / e la virgola. Il mio editore suggerisce di aggiungere spazi bianchi dopo ,: s
toonarmycaptain il

enumeraterestituisce due iterabili, quindi hai bisogno di due posti per metterli. Ma in questo caso non è necessario il secondo iterabile per nulla.
Daniel F,

1
Piuttosto che blahpreferisco usare un trattino basso o doppio, vedi: stackoverflow.com/questions/5893163/…
Andy Royal

2

Una semplice soluzione ricorsiva per la stringa corta:

def split(s, n):
    if len(s) < n:
        return []
    else:
        return [s[:n]] + split(s[n:], n)

print(split('1234567890', 2))

O in tale forma:

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)

, che illustra in modo più esplicito il tipico modello di divisione e conquista nell'approccio ricorsivo (anche se praticamente non è necessario farlo in questo modo)


2

Ero bloccato nello stesso scenario.

Questo ha funzionato per me

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

Produzione

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

1

more_itertools.slicedè stato menzionato prima. Ecco altre quattro opzioni dalla more_itertoolslibreria:

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

Ciascuna di queste ultime opzioni produce il seguente output:

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

La documentazione per le opzioni discusse: grouper, chunked, windowed,split_after


0

Ciò può essere ottenuto con un semplice ciclo.

a = '1234567890a'
result = []

for i in range(0, len(a), 2):
    result.append(a[i : i + 2])
print(result)

L'output è simile a ['12', '34', '56', '78', '90', 'a']


2
Mentre questo codice può rispondere alla domanda, fornendo un contesto aggiuntivo riguardo al perché e / o al modo in cui questo codice risponde alla domanda migliora il suo valore a lungo termine.
β.εηοιτ.βε

2
Questa è la stessa soluzione qui: stackoverflow.com/a/59091507/7851470
Georgy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.