Una soluzione senza l'uso di importazioni sarà quello di convertire la stringa a un iteratore e durante l'iterazione prendere il carattere successivo chiamando successiva sul iteratore:
>>> s = "abcdefghijklmnopqrstuvwxyz"
>>> it = iter(s)
>>> ''.join(next(it, '') + c for c in it)
'badcfehgjilknmporqtsvuxwzy'
Timings:
>>> s = "abcdefghijklmnopqrstuvwxyz" * 10**5
>>> def func_next_no_cache(s):
it = iter(s)
return ''.join([next(it, '') + c for c in it])
...
>>> %timeit func_next_no_cache(s)
1 loops, best of 3: 291 ms per loop
Ma le chiamate a next
in realtà lo stanno rallentando perché per trovare next
Python deve andare ai comandi incorporati a partire dal ambito locale, cerchiamo di memorizzare nella cache e riprovare:
>>> def func_next_cache(s, next=next):
it = iter(s)
return ''.join([next(it, '') + c for c in it])
...
>>> %timeit func_next_cache(s)
1 loops, best of 3: 241 ms per loop
Ma la soluzione più veloce sarà quello di utilizzare itertools.izip_longest
:
>>> from itertools import izip_longest
>>> def func_izip_l(s):
it = iter(s)
return "".join([b+a for a, b in izip_longest(it, it, fillvalue='')])
...
>>> %timeit func_izip_l(s)
1 loops, best of 3: 209 ms per loop
@ codice di Joran è anche molto vicino a questo quando viene utilizzato con una lista, invece di generatore di espressione, ma crea due stringhe supplementari in memoria:
>>> %timeit "".join([b+a for a, b in izip_longest(s[::2], s[1::2], fillvalue="")])
1 loops, best of 3: 212 ms per loop
Nota che dovremmo sempre nutrire una list
-str.join
se la velocità è una preoccupazione: https://stackoverflow.com/a/9061024/846892
Intende la lunghezza di essere ancora sempre? – thefourtheye
@thefourtheye No **. A proposito, il modo in cui ho postato funziona ancora per una stringa con una lunghezza irregolare. – Jack
Cosa ti aspetti dal risultato se vuoi ottenere 3 personaggi? – thefourtheye