Newsgroup: it.comp.lang.perl
Titolo: ordinamento di lista

Ciao,
ho il seguente problema: devo ordinare una lista che puo' contenere solo
numeri (in tal caso e' facile) oppure elementi del tipo
a1,c3,f32,a4.....g21,y1,b2,....z54.
Devo ordinarla in modo tale che si abbia
a1,a2,a3,a4,a5,...a10,a11...b1,b2.....
Se uso  
@list = sort { $a <=> $b } @list;
ottengo: a1,a10,a11....a2,a20,a21...
Qualcuno ha qualche suggerimento?
Grazie in anticipo
Paolo
--
Posted from 
tlvsdy.vim.tlt.alcatel.it
 [151.98.8.244]
via Mailgate.ORG Server - 
http://www.mailgate.org

 ottengo: a1,a10,a11....a2,a20,a21...
 Essendo stringhe, dovresti usare usare cmp invece di <=>
 
 Comunque, se gli elementi sono ESATTAMENTE <stringa><numero>,
 potresti provare
 
  @list = map { $_->[0] }
          sort { $a->[1] cmp $b->[1] ||
	         $a->[2] <=> $b->[2] } 
	  map { [ $_,  /^(\D+)(\d+)$/ ] } 
	  @list;
 
 Ovvero, separa ogni elemento in due parti, stringa e numero, poi ordina
 secondo la stringa e, per stringhe uguali, secondo il valore numerico.
 Maurizio
-- 
Maurizio M. Munafo' / 
mmmu...@usa.net
"Consider Phlebas, who was once handsome and tall as you" (T.S.Eliot)

  secondo la stringa e, per stringhe uguali, secondo il valore numerico.
Rileggo ora meglio il messaggio originale.
Occhio che gli elementi possono anche essere solo numeri, la funzione
precedente non funziona...
Ci vuole qualcosa che sistemi l'array intermedio per evitare le variabili
undefined...
  @list1 = map { [ $_,  /^(\D+)(\d+)$/ ] } @list;
  for (@list1)
    {
      $_->[1] = "" unless defined $_->[1];
      $_->[2] = 0  unless defined $_->[2];
    }
  @list = map { $_->[0] }
          sort { $a->[1] cmp $b->[1] ||
          $a->[2] <=> $b->[2]} 
	  @list1;  
 
che e' equivalente alla codice precedente, con una ripulitura dell'array
intermedio.


...


Ciao,
ho utilizzato i tuoi suggerimenti: hanno lo stesso comportamento cioe'
funzionano
 benissimo sugli array con elementi del tipo a1,.....c97,.. .
Nel caso invece che gli elementi siano numerici puri mi ritrovo lo
stesso array che avevo in input, per cui 
e' inutilizzabile. 
Sto continuando a fare delle prove, se hai altri suggerimenti saranno
bene accolti.
Ciao


Ciao,
una soluzione che ho trovato consiste nell' aggiungere in coda al tuo 
codice questa riga 
@new_list = sort {($a <=> $b)} @list;		  
Funziona con entrambe le tue versioni, anche se mi sembra che cio'
voglia dire 
che non viene eseguito il sort numerico nella tua parte. Potrebbe
essere?
Grazie dell'aiuto.


 bene accolti.
Ho trovato il mio errore...
Prova:
   @list1 = map { [ $_,  /^(\D*)(\d+)$/ ] } @list;
                        ####  ^  '*' al posto di '+'
   for (@list1)
     {
       $_->[1] = "" unless defined $_->[1];
       $_->[2] = 0  unless defined $_->[2];
     }
   @list = map { $_->[0] }
	   sort { $a->[1] cmp $b->[1] ||
	   $a->[2] <=> $b->[2]} @list1;  
Il vecchio pattern non faceva alcun match se il valore era puramente numerico.
Ora sembra funzionare...


 wrote:
Ho verificato che ora anche la prima versione, quella senza vettore
intermedio, funziona se si corregge il match con \D*
  @list = map { $_->[0] }
          sort { $a->[1] cmp $b->[1] ||
	         $a->[2] <=> $b->[2]}  
	  map { [ $_,  /^(\D*)(\d+)$/ ] } @list;
 


Ti ringrazio dell'aiuto, la tua ultima versione funziona bene, l'unico
inghippo e' che quando arrivano elementi del tipo
a1,...a92,b1,...b62,aa1,..aa10,ab1,..., mi trovo
a1,..a97,aa1,...aa10,b1   
mentre vorrei trovarmi
a1,..a97,b1,..b62,...aa1,....
Grazie


 a1,..a97,b1,..b62,...aa1,....
Sei proprio incontentabile! :) Problema vago, risposta vaga...
Prova quest'altra,
  @list = map { $_->[0] }
          sort { length($a->[1]) <=> length($b->[1]) ||
	         $a->[1] cmp $b->[1] ||
		 $a->[2] <=> $b->[2] }  
	  map { [ $_,  /^(\D*)(\d+)$/ ] } @list;
 
che ordina la parte iniziale di stringa per lunghezza, poi alfabeticamente 
ed infine secondo la parte numerica.
