PDA

Visualizza la versione completa : [Python] ordinare per valore assoluto


dosdosdos
05-06-2010, 18:44
Salve a tutti,
devo ordinare una lista secondo il valore assoluto, ma lasciandola inalterata.

Ad esempio:
abs_sort([2,-3,-6,0,4])

ritorna:
[0,2,-3,4,-6]

Non sono riuscito a trovare una funzione del genere in numpy....avete qualche suggerimento?

PS: vorrei trovare una soluzione elegante che non richieda molto spazio!

billiejoex
06-06-2010, 14:52
>>> l = [2,-3,-6,0,4]
>>> sorted(l, key=lambda x: abs(x))
[0, 2, -3, 4, -6]

dosdosdos
06-06-2010, 16:14
Grazie mille!
Posso chiederti come funziona la key? Non sapevo che sort potesse prendere più di un argomento.

billiejoex
06-06-2010, 16:50
- "key" è la chiave utilizzata per ordinare gli elementi lista
- come argomento accetta una funzione alla quale verrà passato un argomento che è un elemento della lista
- tale funzione verrà chiamata tante volte quanti sono gli elementi della lista
- l'ordinamento avverrà in base ai valori di ritorno della funzione


Un comune sort di questo tipo (ovvero quello di default):



>>> l = [5,4,3,2,1]
>>> l.sort()
>>> l
[1, 2, 3, 4, 5]


...lo puoi immaginare alla stregua di questo:



>>> l = [5,4,3,2,1]
>>> l.sort(key=lambda x: x)
>>> l
[1, 2, 3, 4, 5]


Questi fanno la stessa cosa in quanto la funzione lambda ritorna i singoli elementi della lista cosi come sono (lambda x: x), senza applicare nessuna modifica.

Cambiando la logica della funzione, come mostrato nel mio primo messaggio, non fai altro che modificare i singoli elementi della lista ad ogni iterazione utilizzando un tuo criterio ben specifico.

Nel mio primo messaggio si applica abs() ad ogni elemento della lista e il sort è applicato proprio a quello che esce fuori da abs(x) anzichè x stesso, come invece accade di default.

In questo modo, "internamente", gli elementi della lista non appariranno più come:

[2, -3, -6, 0, 4]

...ma:

[abs(2), abs(-3), abs(-6), abs(0), abs(4)]

...che sarà risolto in:

[2, 3, 6, 0, 4]

...e solo infine ordinato:

[0, 2, 3, 4, 6]

billiejoex
06-06-2010, 17:05
Piccola nota, giusto per chiarezza, "tua_lista.sort()" e "sorted(tua_lista)" si differenziano nel fatto che la prima effettua un ordinalmento della lista stessa, che di fatto cambierà l'ordine dei suoi elementi, mentre sorted() ti ritorna una copia della lista ordinata, lasciando l'originale invariata.

Ovviamente sorted() è più dispendioso in termini di memoria.

dosdosdos
06-06-2010, 18:12
Grazie mille sei stato davvero chiaro! :)

Colgo l'occasione per descrivere il problema in cui dovevo applicarla:

devo ordinare una lista di array in base al valore assoluto del primo vettore:

array([ [ 3, -2, -4],
[ 1, 7, -2],
[ 5, 8, 9],
[ -6, 0, 12] ])

il metodo deve restituire:

array([ [ -2, 3, -4],
[ 7, 1, -2],
[ 8, 5, 9],
[ 0, -6, 12] ])

ossia ordinare il primo array per il valore assoluto degli elementi e portarmi dietro le colonne.

Come posso sfruttare il sort per risolvere tale problema in modo pythonesco?
Non vorrei mettermi a dichiarare liste di appoggio o simili :spy:

billiejoex
06-06-2010, 18:32
Uhm... non credo di aver capito.
Inanzitutto come ottieni questo?

array([ [ 3, -2, -4],
[ 1, 7, -2],
[ 5, 8, 9],
[ -6, 0, 12] ])

Utilizzando il modulo array della libreria standard?
Se si puoi incollare un po' di codice?

dosdosdos
06-06-2010, 18:43
scusa...ho creato confusione!

ho in input
lista = [[3, -2, -4], [1, 7, -2], [5, 8, 9], [-6, 0, 12]]

voglio ottenere
lista_ordinata = [[-2, 3, -4], [7, 1, -2], [8, 5, 9], [0, -6, 12]]

Il criterio d'ordine si basa solo sulla prima lista [-2, 3, -4] e le altre liste vengono ordinate di consdeguenza

billiejoex
06-06-2010, 18:54
Non capisco che logica di ordinamento vuoi applicare.
La prima lista mi è chiara:

[3, -2, -4]

...diventa:

[-2, 3, -4]

...in base ad un ordinamento di tipo assoluto.
Le altre 3 non capisco in che modo le hai ordinate.
Ad esempio la seconda da [1, 7, -2] diventa [7, 1, -2], che ovviamente non segue un ordine crescente come la prima.

Inoltre non capisco se vuoi ordinare la lista in senso "generale" (ovvero spostare le liste al suo interno secondo un certo criterio) oppure ordinare gli elementi interni delle singole liste, lasciando le posizioni delle liste invariate.

dosdosdos
06-06-2010, 18:59
le liste seguenti alla prima devono essere riordinate seguendo gli spostamenti della prima: in pratica le colonne si spostano tutte insieme agli elementi della prima riga.

[[3, -2, -4],
[1, 7, -2],
[5, 8, 9],
[-6, 0, 12]]

ottengo:

[[-2, 3, -4],
[7, 1, -2],
[8, 5, 9],
[0, -6, 12]]

se osservi le colonne vedrai che rimangono invariate!
Ordinando la prima riga gli elementi si portano dietro tutta la colonna :)

Loading