Risposte:
È possibile utilizzare la reversed
funzione per questo come:
>>> array=[0,10,20,40]
>>> for i in reversed(array):
... print(i)
Si noti che reversed(...)
non restituisce un elenco. È possibile ottenere un elenco invertito utilizzando list(reversed(array))
.
reverse
potrebbe essere più veloce, tuttavia, se non è necessario eseguire il cast per elencarlo in seguito.
reversed()
invece di tagliare? Leggi lo Zen di Python, regola numero 7: la leggibilità conta!
>>> L = [0,10,20,40]
>>> L[::-1]
[40, 20, 10, 0]
La sintassi della sezione estesa è spiegata bene nella Novità di Python per il rilascio2.3.5
Su richiesta speciale in un commento questa è la documentazione di fetta più aggiornata .
reversed
restituisce un listreverseiterator
oggetto (Python 2.7.x), che deve quindi essere ripetuto attraverso - reverse slicing restituisce un elenco / tuple / str invertito (a seconda di ciò che stai tagliando). @Einar Petersen che sta invertendo una stringa, quindi l'output è corretto. Prova:co2=['ae','ad','ac','ab','aa','z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'] >>> co2[::-1]
>>> L = [0,10,20,40]
>>> L.reverse()
>>> L
[40, 20, 10, 0]
O
>>> L[::-1]
[40, 20, 10, 0]
L=L[::-1]
quello di invertire effettivamente la lista, altrimenti stai solo restituendo i valori al contrario
b = l[-n:] b.reverse() l = b + l[:len(l) - n]
Penso che il modo migliore per invertire un elenco in Python sia fare:
a = [1,2,3,4]
a = a[::-1]
print(a)
>>> [4,3,2,1]
Il lavoro è finito e ora hai un elenco invertito.
Per invertire lo stesso elenco utilizzare:
array.reverse()
Per assegnare un elenco invertito in un altro elenco utilizzare:
newArray = array[::-1]
Usare lo slicing, ad esempio array = array [:: - 1], è un trucco accurato e molto Pythonic, ma forse un po 'oscuro per i neofiti. L'uso del metodo reverse () è un buon modo per passare alla codifica quotidiana perché è facilmente leggibile.
Tuttavia, se è necessario invertire un elenco in atto come in una domanda di intervista, probabilmente non sarà possibile utilizzare metodi integrati come questi. L'intervistatore esaminerà il modo in cui affronti il problema anziché la profondità della conoscenza di Python, è necessario un approccio algoritmico. L'esempio seguente, usando uno scambio classico, potrebbe essere un modo per farlo: -
def reverse_in_place(lst): # Declare a function
size = len(lst) # Get the length of the sequence
hiindex = size - 1
its = size/2 # Number of iterations required
for i in xrange(0, its): # i is the low index pointer
temp = lst[hiindex] # Perform a classic swap
lst[hiindex] = lst[i]
lst[i] = temp
hiindex -= 1 # Decrement the high index pointer
print "Done!"
# Now test it!!
array = [2, 5, 8, 9, 12, 19, 25, 27, 32, 60, 65, 1, 7, 24, 124, 654]
print array # Print the original sequence
reverse_in_place(array) # Call the function passing the list
print array # Print reversed list
**The result:**
[2, 5, 8, 9, 12, 19, 25, 27, 32, 60, 65, 1, 7, 24, 124, 654]
Done!
[654, 124, 24, 7, 1, 65, 60, 32, 27, 25, 19, 12, 9, 8, 5, 2]
Nota che questo non funzionerà su Tuple o sequenze di stringhe, poiché stringhe e tuple sono immutabili, cioè non puoi scrivere in esse per cambiare elementi.
lst[hiindex], lst[i] = lst[i], lst[hiindex]
, credo ... ;-)
array[::-1]
è perfettamente leggibile ed perfettamente esplicito se conosci Python . "Leggibile" non significa "qualcuno che non ha mai usato Python slicing prima deve essere in grado di leggerlo"; la [::-1]
porzione di inversione è un linguaggio ridicolmente comune in Python (lo troverai sempre nel codice esistente), ed è perfettamente leggibile se usi regolarmente Python . Certo, first10 = []
, for i in range(10): first10.append(array[i])
è chiara ed esplicita, ma che non lo rende migliore rispetto first10 = array[:10]
.
Trovo (contrariamente ad alcuni altri suggerimenti) che l.reverse()
è di gran lunga il modo più veloce per invertire un lungo elenco in Python 3 e 2. Sarei interessato a sapere se altri possono replicare questi tempi.
l[::-1]
è probabilmente più lento perché copia l'elenco prima di invertirlo. L'aggiunta della list()
chiamata attorno all'iteratore effettuata reversed(l)
deve aggiungere un certo sovraccarico. Naturalmente se si desidera una copia dell'elenco o un iteratore, utilizzare i rispettivi metodi, ma se si desidera invertire l'elenco, l.reverse()
sembra essere il modo più veloce.
funzioni
def rev_list1(l):
return l[::-1]
def rev_list2(l):
return list(reversed(l))
def rev_list3(l):
l.reverse()
return l
Elenco
l = list(range(1000000))
Tempi di Python 3.5
timeit(lambda: rev_list1(l), number=1000)
# 6.48
timeit(lambda: rev_list2(l), number=1000)
# 7.13
timeit(lambda: rev_list3(l), number=1000)
# 0.44
Tempi di Python 2.7
timeit(lambda: rev_list1(l), number=1000)
# 6.76
timeit(lambda: rev_list2(l), number=1000)
# 9.18
timeit(lambda: rev_list3(l), number=1000)
# 0.46
list.reverse
è il più veloce, perché si inverte sul posto
list.reverse()
è il più veloce, ma stai penalizzando reversed
(che è meglio usare quando non vuoi un nuovo list
, solo per iterare un esistente list
in ordine inverso senza mutare l'originale), e la fetta (che evita anche di mutare l'originale list
ed è generalmente più veloce di reversed
quando l'input è piccolo). Sì, se non hai bisogno della copia, tutto ciò che le copie sono più costose, ma molte volte, non vuoi mutare il valore originale.
reversed
perdalist.reverse()
ancora così, ma dato che non muta l'input list
, è meglio in molti casi. La perdita per reversed
è piccola (~ 1/6 più lunga di list.reverse()
).
>>> list1 = [1,2,3]
>>> reversed_list = list(reversed(list1))
>>> reversed_list
>>> [3, 2, 1]
array=[0,10,20,40]
for e in reversed(array):
print e
L'utilizzo di reverse (array) sarebbe probabilmente il percorso migliore.
>>> array = [1,2,3,4]
>>> for item in reversed(array):
>>> print item
Dovresti capire come implementarlo senza usare il built-in reversed
.
def reverse(a):
midpoint = len(a)/2
for item in a[:midpoint]:
otherside = (len(a) - a.index(item)) - 1
temp = a[otherside]
a[otherside] = a[a.index(item)]
a[a.index(item)] = temp
return a
Questo dovrebbe richiedere tempo O (N).
Esistono diverse risposte valide, ma sparse e la maggior parte non indica le differenze fondamentali di ciascun approccio.
Nel complesso, è meglio utilizzare le funzioni / i metodi integrati per invertire, come con qualsiasi funzione. In questo caso, sono circa da 2 a 8 volte più veloci su elenchi brevi (10 articoli) e fino a ~ 300 + volte più veloci su elenchi lunghi rispetto a quelli creati manualmente come mezzo di indicizzazione. Questo ha senso in quanto hanno esperti che li creano, controllano e ottimizzano. Sono anche meno inclini a difetti e hanno maggiori probabilità di gestire casi limite e angolari.
Valuta anche se vuoi:
object.reverse()
metodoreversed(object)
che crea l'iteratoreobject[::-1]
Ecco l'inizio del mio script di test per i metodi trattati. Metti insieme tutti i frammenti di codice in questa risposta per creare uno script che eseguirà tutti i diversi modi di invertire un elenco e cronometrare ciascuno (output mostrato nell'ultima sezione).
from timeit import timeit
from copy import copy
def time_str_ms(t):
return '{0:8.2f} ms'.format(t * 1000)
Se l'obiettivo è solo quello di invertire l'ordine degli elementi in un elenco esistente, senza passare in rassegna su di essi o ottenere una copia con cui lavorare, utilizzare la <list>.reverse()
funzione. Eseguilo direttamente su un oggetto elenco e l'ordine di tutti gli elementi verrà invertito:
Si noti che quanto segue invertirà la variabile originale che viene fornita, anche se restituisce anche l'elenco invertito. cioè puoi creare una copia usando questa funzione di output. In genere, non avresti una funzione per questo, ma l'ho fatto per usare il codice di timing alla fine.
Testeremo le prestazioni di questi due modi: prima invertendo un elenco sul posto (cambia l'elenco originale), quindi copiando l'elenco e invertendolo successivamente.
def rev_in_place(mylist):
mylist.reverse()
return mylist
def rev_copy_reverse(mylist):
a = copy(mylist)
a.reverse()
return a
obj[::-1]
Il metodo di suddivisione dell'indice incorporato consente di eseguire una copia di parte di qualsiasi oggetto indicizzato.
La sintassi generica è: <object>[first_index:last_index:step]
. Per sfruttare affettare per creare un semplice elenco invertita, uso: <list>[::-1]
. Quando si lascia un'opzione vuota, li imposta sui valori predefiniti del primo e dell'ultimo elemento dell'oggetto (invertiti se la dimensione del passo è negativa).
L'indicizzazione consente di utilizzare numeri negativi, che contano dalla fine dell'indice dell'oggetto all'indietro (ovvero -2 è il penultimo oggetto). Quando la dimensione del passo è negativa, inizierà con l'ultimo elemento e indicizzerà all'indietro di tale importo. C'è una logica di inizio-fine associata a questo che è stata ottimizzata.
def rev_slice(mylist):
a = mylist[::-1]
return a
reversed(obj)
funzione iteratoreC'è una reversed(indexed_object)
funzione:
Prova con un iteratore non elaborato e crea un elenco dall'iteratore.
def reversed_iterator(mylist):
a = reversed(mylist)
return a
def reversed_with_list(mylist):
a = list(reversed(mylist))
return a
Come i tempi mostreranno, creare i tuoi metodi di indicizzazione è una cattiva idea. Usa i metodi integrati a meno che tu non abbia bisogno di fare qualcosa di veramente personalizzato.
Detto questo, non c'è un'enorme penalità con elenchi più piccoli, ma quando si aumenta la penalità diventa enorme. Sono sicuro che il mio codice qui sotto potrebbe essere ottimizzato, ma mi atterrò con i metodi integrati.
def rev_manual_pos_gen(mylist):
max_index = len(mylist) - 1
return [ mylist[max_index - index] for index in range(len(mylist)) ]
def rev_manual_neg_gen(mylist):
## index is 0 to 9, but we need -1 to -10
return [ mylist[-index-1] for index in range(len(mylist)) ]
def rev_manual_index_loop(mylist):
a = []
reverse_index = len(mylist) - 1
for index in range(len(mylist)):
a.append(mylist[reverse_index - index])
return a
def rev_manual_loop(mylist):
a = []
reverse_index = len(mylist)
for index, _ in enumerate(mylist):
reverse_index -= 1
a.append(mylist[reverse_index])
return a
Di seguito è riportato il resto dello script per cronometrare ogni metodo di inversione. Mostra che l'inversione in atto con obj.reverse()
e la creazione reversed(obj)
dell'iteratore sono sempre le più veloci, mentre l'uso delle sezioni è il modo più veloce per creare una copia.
Dimostra anche di non provare a creare un modo per farlo da soli a meno che tu non debba farlo!
loops_to_test = 100000
number_of_items = 10
list_to_reverse = list(range(number_of_items))
if number_of_items < 15:
print("a: {}".format(list_to_reverse))
print('Loops: {:,}'.format(loops_to_test))
# List of the functions we want to test with the timer, in print order
fcns = [rev_in_place, reversed_iterator, rev_slice, rev_copy_reverse,
reversed_with_list, rev_manual_pos_gen, rev_manual_neg_gen,
rev_manual_index_loop, rev_manual_loop]
max_name_string = max([ len(fcn.__name__) for fcn in fcns ])
for fcn in fcns:
a = copy(list_to_reverse) # copy to start fresh each loop
out_str = ' | out = {}'.format(fcn(a)) if number_of_items < 15 else ''
# Time in ms for the given # of loops on this fcn
time_str = time_str_ms(timeit(lambda: fcn(a), number=loops_to_test))
# Get the output string for this function
fcn_str = '{}(a):'.format(fcn.__name__)
# Add the correct string length to accommodate the maximum fcn name
format_str = '{{fx:{}s}} {{time}}{{rev}}'.format(max_name_string + 4)
print(format_str.format(fx=fcn_str, time=time_str, rev=out_str))
I risultati mostrano che il ridimensionamento funziona meglio con i metodi integrati più adatti per una determinata attività. In altre parole, con l'aumentare del conteggio degli elementi dell'oggetto, i metodi integrati iniziano ad avere risultati di prestazioni di gran lunga superiori.
Stai anche meglio usando il miglior metodo integrato che ottiene direttamente ciò di cui hai bisogno piuttosto che mettere insieme le cose. vale a dire che lo slicing è la cosa migliore se hai bisogno di una copia dell'elenco invertito: è più veloce della creazione di un elenco dalla reversed()
funzione e più veloce rispetto alla creazione di una copia dell'elenco e quindi alla creazione di una copia sul posto obj.reverse()
. Ma se uno di questi metodi è davvero tutto ciò di cui hai bisogno, sono più veloci, ma mai più del doppio della velocità. Nel frattempo, i metodi personalizzati e manuali possono richiedere ordini di grandezza più lunghi, specialmente con elenchi molto grandi.
Per il ridimensionamento, con un elenco di 1000 voci, la reversed(<list>)
chiamata di funzione impiega ~ 30 ms per impostare l'iteratore, l'inversione sul posto impiega solo ~ 55 ms, usando il metodo slice impiega ~ 210 ms per creare una copia dell'elenco rovesciato completo, ma il metodo manuale più veloce che ho realizzato ha richiesto ~ 8400 ms !!
Con 2 elementi nell'elenco:
a: [0, 1]
Loops: 100,000
rev_in_place(a): 24.70 ms | out = [1, 0]
reversed_iterator(a): 30.48 ms | out = <list_reverseiterator object at 0x0000020242580408>
rev_slice(a): 31.65 ms | out = [1, 0]
rev_copy_reverse(a): 63.42 ms | out = [1, 0]
reversed_with_list(a): 48.65 ms | out = [1, 0]
rev_manual_pos_gen(a): 98.94 ms | out = [1, 0]
rev_manual_neg_gen(a): 88.11 ms | out = [1, 0]
rev_manual_index_loop(a): 87.23 ms | out = [1, 0]
rev_manual_loop(a): 79.24 ms | out = [1, 0]
Con 10 voci nell'elenco:
rev_in_place(a): 23.39 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
reversed_iterator(a): 30.23 ms | out = <list_reverseiterator object at 0x00000290A3CB0388>
rev_slice(a): 36.01 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_copy_reverse(a): 64.67 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
reversed_with_list(a): 50.77 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_pos_gen(a): 162.83 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_neg_gen(a): 167.43 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_index_loop(a): 152.04 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_loop(a): 183.01 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
E con 1000 articoli nell'elenco:
rev_in_place(a): 56.37 ms
reversed_iterator(a): 30.47 ms
rev_slice(a): 211.42 ms
rev_copy_reverse(a): 295.74 ms
reversed_with_list(a): 418.45 ms
rev_manual_pos_gen(a): 8410.01 ms
rev_manual_neg_gen(a): 11054.84 ms
rev_manual_index_loop(a): 10543.11 ms
rev_manual_loop(a): 15472.66 ms
Se si desidera memorizzare gli elementi dell'elenco invertito in un'altra variabile, è possibile utilizzare revArray = array[::-1]
o revArray = list(reversed(array))
.
Ma la prima variante è leggermente più veloce:
z = range(1000000)
startTimeTic = time.time()
y = z[::-1]
print("Time: %s s" % (time.time() - startTimeTic))
f = range(1000000)
startTimeTic = time.time()
g = list(reversed(f))
print("Time: %s s" % (time.time() - startTimeTic))
Produzione:
Time: 0.00489711761475 s
Time: 0.00609302520752 s
timeit
.
In Python, anche l'ordine delle liste può essere manipolato con l' ordinamento , organizzando le variabili in ordine numerico / alfabetico:
print(sorted(my_list))
my_list.sort(), print(my_list)
Puoi ordinare con il flag "reverse = True" :
print(sorted(my_list, reverse=True))
o
my_list.sort(reverse=True), print(my_list)
Forse non vuoi ordinare i valori, ma solo invertire i valori. Quindi possiamo farlo in questo modo:
print(list(reversed(my_list)))
** I numeri hanno la priorità sull'alfabeto nell'ordine di elenco. L'organizzazione dei valori di Python è fantastica.
Usando alcune logiche della vecchia scuola per esercitarsi nelle interviste.
Scambiare numeri da davanti a dietro. Utilizzando due puntatori
index[0] and index[last]
def reverse(array):
n = array
first = 0
last = len(array) - 1
while first < last:
holder = n[first]
n[first] = n[last]
n[last] = holder
first += 1
last -= 1
return n
input -> [-1 ,1, 2, 3, 4, 5, 6]
output -> [6, 1, 2, 3, 4, 5, -1]
Puoi anche utilizzare il complemento bit a bit dell'indice di array per scorrere l'array al contrario:
>>> array = [0, 10, 20, 40]
>>> [array[~i] for i, _ in enumerate(array)]
[40, 20, 10, 0]
Qualunque cosa tu faccia, non farlo in questo modo.
Un'altra soluzione sarebbe usare numpy.flip per questo
import numpy as np
array = [0, 10, 20, 40]
list(np.flip(array))
[40, 20, 10, 0]
A rigor di termini, la domanda non è come restituire un elenco al contrario, ma piuttosto come invertire un elenco con un nome di elenco di esempio array
.
Per invertire un elenco denominato "array"
use array.reverse()
.
Il metodo slice incredibilmente utile come descritto può anche essere utilizzato per invertire un elenco in atto definendo l'elenco come una modifica suddivisa di se stesso utilizzando array = array[::-1]
.
array[:] = array[::-1]
def reverse(text):
output = []
for i in range(len(text)-1, -1, -1):
output.append(text[i])
return output
Con una quantità minima di funzioni integrate, supponendo che siano le impostazioni dell'intervista
array = [1, 2, 3, 4, 5, 6,7, 8]
inverse = [] #create container for inverse array
length = len(array) #to iterate later, returns 8
counter = length - 1 #because the 8th element is on position 7 (as python starts from 0)
for i in range(length):
inverse.append(array[counter])
counter -= 1
print(inverse)
La traduzione più diretta dei tuoi requisiti in Python è questa for
affermazione:
for i in xrange(len(array) - 1, -1, -1):
print i, array[i]
Questo è piuttosto criptico ma può essere utile.
def reverse(my_list):
L = len(my_list)
for i in range(L/2):
my_list[i], my_list[L-i - 1] = my_list[L-i-1], my_list[i]
return my_list
//
operatore di divisione del pavimento.
Potresti sempre trattare l'elenco come uno stack semplicemente estraendo gli elementi dalla parte superiore dello stack dal retro dell'elenco. In questo modo sfrutti le caratteristiche first in last out di uno stack. Ovviamente stai consumando il primo array. Mi piace questo metodo in quanto è piuttosto intuitivo in quanto vedi un elenco che viene consumato dal back-end mentre l'altro viene creato dal front-end.
>>> l = [1,2,3,4,5,6]; nl=[]
>>> while l:
nl.append(l.pop())
>>> print nl
[6, 5, 4, 3, 2, 1]
list_data = [1,2,3,4,5]
l = len(list_data)
i=l+1
rev_data = []
while l>0:
j=i-l
l-=1
rev_data.append(list_data[-j])
print "After Rev:- %s" %rev_data
uso
print(reversed(list_name))
Ecco un modo per valutare pigramente il contrario usando un generatore :
def reverse(seq):
for x in range(len(seq), -1, -1): #Iterate through a sequence starting from -1 and increasing by -1.
yield seq[x] #Yield a value to the generator
Ora scorrere in questo modo:
for x in reverse([1, 2, 3]):
print(x)
Se hai bisogno di un elenco:
l = list(reverse([1, 2, 3]))
Esistono 3 metodi per ottenere l'elenco invertito:
Metodo di affettatura 1: reversed_array = array[-1::-1]
Metodo di affettatura 2:
reversed_array2 = array[::-1]
Utilizzando la funzione integrata: reversed_array = array.reverse()
La terza funzione ha effettivamente invertito l'oggetto elenco in atto. Ciò significa che non viene mantenuta alcuna copia di dati incontaminati. Questo è un buon approccio se non si desidera mantenere la versione precedente. Ma non sembra essere una soluzione se vuoi la versione incontaminata e invertita.