2012-12-31 12 views
33

La funzione di intervallo consente la concatenazione? Come voglio fare un range(30) & concatenare con range(2000, 5002). Quindi il mio gamma concatenati sarà 0, 1, 2, ... 29, 2000, 2001, ... 5001Concatenazione di due risultati di una gamma di funzioni

codice come questo non funziona sul mio ultimo python (ver: 3.3.0)

range(30) + range(2000, 5002) 
+0

versione di Python? –

+0

la versione del mio python è la versione 3.3.0 .. ho anche aggiornato nella mia domanda – MAG

+1

Cosa vuoi ottenere come risultato (come in, che tipo di dati - un elenco semplice, un generatore, qualcos'altro)? Cosa vuoi fare con il risultato? –

risposta

34

È possibile utilizzare itertools.chain per questo:

from itertools import chain 
concatenated = chain(range(30), range(2000, 5002)) 
for i in concatenated: 
    ... 

E ' funziona per iterables arbitrari. Si noti che esiste una differenza nel comportamento di range() tra Python 2 e 3 che è necessario conoscere: in Python 2 range restituisce un elenco e in Python3 un iteratore, che è efficiente in termini di memoria, ma non sempre desiderabile.

Le liste possono essere concatenate con +, gli iteratori non possono.

3

range() in Python 2.x restituisce una lista:

>>> range(10) 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

xrange() in Python 2.x restituisce un iteratore:

>>> xrange(10) 
xrange(10) 

E in Python 3 range() restituisce anche un iteratore:

>>> r = range(10) 
>>> iterator = r.__iter__() 
>>> iterator.__next__() 
0 
>>> iterator.__next__() 
1 
>>> iterator.__next__() 
2 

Quindi è chiaro che non è possibile concatenare altri iteratori utilizzando chain() come indicato dall'altro utente.

+1

la tua risposta è utile, ma non fornisce una soluzione. –

23

Può essere utilizzato utilizzando list-comprehension.

>>> [i for j in (range(10), range(15, 20)) for i in j] 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 18, 19] 

Funziona per la richiesta, ma è una risposta lunga, quindi non lo posterò qui.

nota: può essere trasformato in un generatore per aumentare le prestazioni:

for x in (i for j in (range(30), range(2000, 5002)) for i in j): 
    # code 

o anche in una variabile generatore.

gen = (i for j in (range(30), range(2000, 5002)) for i in j) 
for x in gen: 
    # code 
+3

+1 per nessuna dipendenza aggiuntiva – mkind

+0

@mkind grazie, odio le dipendenze, le persone saltano sempre e rispondono con tonnellate di importazioni e librerie, ma non sono sempre disponibili, e spesso fanno la stessa cosa che fa il normale codice, solo avvolto in un pacchetto, non è magico. :) –

+7

Non penso che _non usare le librerie standard_ sia una virtù a sé stante, ma questa è una bella risposta. –

17

Mi piacciono le soluzioni più semplici possibili (compresa l'efficienza). Non è sempre chiaro se la soluzione sia tale. Ad ogni modo, lo range() in Python 3 è un generatore. Puoi racchiuderlo in qualsiasi costrutto che esegue l'iterazione. Lo list() è in grado di costruire un valore di lista da qualsiasi iterabile. L'operatore + per le liste concatena. Sto usando valori più piccoli nell'esempio:

>>> list(range(5)) 
[0, 1, 2, 3, 4] 
>>> list(range(10, 20)) 
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 
>>> list(range(5)) + list(range(10,20)) 
[0, 1, 2, 3, 4, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 

Questo è ciò che ha fatto esattamente range(5) + range(10, 20) in Python 2.5 - perché range() restituito un elenco.

In Python 3, è utile solo se si vuole veramente costruire l'elenco. Altrimenti, raccomando la soluzione Lev Levitsky's con itertools.chain.La documentazione dimostra anche l'implementazione molto semplice:

def chain(*iterables): 
    # chain('ABC', 'DEF') --> A B C D E F 
    for it in iterables: 
     for element in it: 
      yield element 

La soluzione da Inbar Rose va bene e funzionalmente equivalente. Ad ogni modo, il mio +1 va a Lev Levitsky e al suo argomento sull'uso delle librerie standard. Da Lo Zen di Python ...

A fronte di ambiguità, rifiutare la tentazione di indovinare.

#!python3 
import timeit 
number = 10000 

t = timeit.timeit('''\ 
for i in itertools.chain(range(30), range(2000, 5002)): 
    pass 
''', 
'import itertools', number=number) 
print('itertools:', t/number * 1000000, 'microsec/one execution') 

t = timeit.timeit('''\ 
for x in (i for j in (range(30), range(2000, 5002)) for i in j): 
    pass 
''', number=number) 
print('generator expression:', t/number * 1000000, 'microsec/one execution') 

A mio parere, il itertools.chain è più leggibile. Ma cosa è davvero importante ...

itertools: 264.4522138986938 microsec/one execution 
generator expression: 785.3081048010291 microsec/one execution 

... è circa 3 volte più veloce.

+0

questo è grandioso, ammetterò la sconfitta con moduli di libreria standard costruiti in modo efficiente. ma il tuo tempismo è strano, sulla mia macchina dopo numerosi test, ho trovato che la mia soluzione è solo circa 1,8 volte più lenta, anziché 3 volte più lenta. ma è ancora più lento. –

+0

È sicuramente dipendente dall'hardware e potrebbe anche dipendere dal SO. Ho usato il mio computer piuttosto obsoleto con AMD Athlon 64 X2 Dual Core Processor 3800+ a 2,01 GHz, con 3 GB di memoria. Il sistema operativo è Windows 7 Home Premium a 64 bit (sia il processore che il punteggio di memoria sono solo 4,9 - http://windows.microsoft.com/en-US/windows7/What-is-the-Windows-Experience-Index) . Non sono sicuro dell'attuazione di Python. Supponi, potresti avere più core del processore. – pepr

2

Con l'aiuto del metodo di estensione, è possibile concatenare due elenchi.

>>> a = list(range(1,10)) 
>>> a.extend(range(100,105)) 
>>> a 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 101, 102, 103, 104] 
+2

Questo è per Python 2, l'OP utilizza Python 3. –

+1

Extend non è una parola chiave, è un metodo sugli elenchi Python. – user7610

1

Sono venuto a questa domanda, perché stavo cercando di concatenare un numero imprecisato di catene, che potrebbero sovrapporsi, e non volevo valori ripetuti nel iteratore finale. La mia soluzione era quella di utilizzare set e union operatore in questo modo:

range1 = range(1,4) 
range2 = range(2,6) 
concatenated = set.union(set(range1), set(range2) 
for i in concatenated: 
    print(i)