Newsgroup: it.comp.lang.perl
Titolo: Ordinare Array

Ho un array di questo tipo (tutto su dbm)
*Il numero tra parentesi è un numero ID
*Time è la funzioni di perl e unix che rappresenta i secondi dal 1970...
(1) => time
(2) => time
(3) => time...
etc...
Come faccio ad ordinare Le chiavi in base all'ordine decrescente dei 
Valori?
(Con un file bello grosso che prestazioni in termini di velocità ho?)
+
Avrei bisogno poi di suddividere in pagine da 10 IDs ciascuna e poter 
sfogliare queste pagine:
Io pensavo di:
1) leggere tutto il file DBM e fare il sort da me richiesto che va in 
@SORTED
2) a pagina zero prendere i primi 10 valori di SORTED [ da 0 a 9 ... ]
3) a pagina 1 prendere i seguenti (1x10) valori di... [ da 9 a 19 di 
@SORTED ]
3) a pagina 2 prendere i seguenti (2x10) valori di... [ da 20 a 29 di 
... ]
4) etc...
Ho molte difficolta a buttare giù le righe in PERL...non so adoperare 
bene le funzioni su array
Grazie...

Cercherň di spiegarmi  meglio anche se il concetto č semplice:
Il file "time.dbm" contiene la coppia CHIAVE => VALORE formata da:
  CHIAVE(numero ID univoco ++) => VALORE(valore di ritorno della 
funzione "time" NON sempre consecutiva*)
*Avvolte puň venir modificato il valore di alcune chiavi con  ID 
precedenti al valore dell ID attuale
quindi per scrivere i valori vado con:
[code]
$ID ++;
   dbmopen(%HASH, "time.dbm" , 0644) || die "Can't open!\n";
    $HASH{$ID} = time;
   dbmclose{%HASH}
[/code]
e per leggere faro:
[code]
dbmopen(%HASH, "time.dbm" , 0644) || die "Can't open!\n";
   %NEW_HASH = %HASH; # ottengo il contenuto del file...
dbmclose;
 
[/code]
ora devo fare in modo che in @SORT_ARRAY ci siano i valori ID di 
$NEW_HASH ma ordinati in base ai valori "crescenti" di $NEW_HASH
per farvi capire:
[code]
 $SORT_ARRAY[3]; # contiene: 01233
 $SORT_ARRAY[1]; # contiene: 01234
 $SORT_ARRAY[5]; # contiene: 01235
etc...
[/code]
Infine avrei bisogno di splittare l'array in gruppi di 10 valori...in 
parole povere di far vedere in piů pagine 10 IDs dell'array alla 
volta...una specie di "Paginazione" dell'array...
Credo che il concetto di quello che ho bisogno sia ben chiaro!
Grazie a tutti

Credo che il concetto di quello che ho bisogno sia ben chiaro!
Meno chiaro è dove sia la difficoltà. Non sai ordinare un array?
     @sorted = sort @array;
Non sai impostare un ciclo?
    sub stampa_pagina {
       my $pagina = shift;
       my $inizio = $pagina * 10;
       my $fine   = $inizio + 9;
       for my $j ($inizio..$fine) {
           print $SORT_ARRAY[$j];
       }
    }
    stampa_pagina(3);
Se i valori ID non sono consecutivi (o, al limite, non sono neppure
numerici), si tratta di aggiungere un livello di indirezione (e ti
rimando per questo al suddetto thread "Hash"); se vuoi fare altro che
stamparli, si tratta di fare l'altro che vuoi fare.
Quello che mi viene da pensare, comunque, è che piuttosto che
risolvere con un ordinamento in memoria, tu abbia bisogno di una
struttura dati su disco diversa (un database indicizzato o un hash
inverso), che ti consenta di estrarre direttamente i dati nell'ordine
giusto.      
Ciao.

Grazie ma ho finalmente risolto...
[code]
# Ordino...
my @SORTED_ARRAY = sort { $HASH{$b} <=> $HASH{$a} } keys %HASH;
undef %HASH; # Libero la memoria...
# Divido in pagine da $rows...
# $Current_page è il valore della pagina corrente ed arriva tramite 
cgi->param();
my $rows = 10;
if (!$Current_page) {$Current_page = 1};
my $end = (($Current_page * $rows)-1);
my $start   = (($Current_page * $rows)-$rows);
my $total_page = int( scalar(@SORTED_ARRAY) / $rows );
$total_page++ if ( scalar(@SORTED_ARRAY) % 10 != 0);
my $page_prev = $Current_page - 1;
if ($Current_page <= 1) { $page_prev = false };
my $page_next = $Current_page + 1;
if ($Current_page >=  $total_page) { $page_next = false };
my @DIECI_IDS;
@DIECI_IDS = @SORTED_ARRAY[$start .. $end];
undef @SORTED_ARRAY; # Libero la memoria...
...
if ($page_prev) { ... ".cgi?Current_page="."$page_prev" } else { ... # 
non mostrare la freccia "prev" };
if ($page_next) { ... ".cgi?Current_page="."$page_next" } else { ... # 
non mostrare la freccia "next" };
[/code]

 
Ho eseguito il codice di cui abbiamo parlato su di un file .dbm con 
100.000 chiavi su di un g3 300Mhz (imac/apple) con MacOSX ... i 
risultati sono disastrosi...42Sec per riordinare i record!!! per non 
parlare di quanta Ram mi impegna...
Capisco che magari gli host in rete dove gira il Perl hanno processori 
intel 10 volte piů potenti...perň non so prorpio cosa 
inventarmi...Possibile che non ci sia un'altra soluzione?

inventarmi...Possibile che non ci sia un'altra soluzione?
Ma certo che c'è un'altra soluzione, come mi pare di averti già detto: usa
un database già ordinato sui valori. Un database .dbm con hash inverso a
quello attuale, o un database di tipo diverso con un indice sul campo che
ti interessa.
Poi può darsi che si possa anche migliorare l'algoritmo di ordinamento, e
usare qualche strategia vuoi per risparmiare memoria vuoi per accelerare
l'ordinamento, ma sono tutti palliativi.
Ciao.

 un database già ordinato sui valori. 
e come faccio? faccio il sort prima di scriverli?

,
scriveva:

Io non so in dettaglio che possibilità diano i database .dbm, e se tu sia
costretto ad usare solo questi o abbia modo di usare altri tipi di database
e quali. L'idea è che, in una situazione priva di vincoli, ordinare i dati
è un problema del database. Tu ti limiti a registrarli, e poi gli chiedi di
restituirteli ordinati e il motore del database provvede a farlo nel modo
più efficiente possibile.
Non so se tu sia o possa metterti in una tale situazione ideale. La
risposta dipende da quanto tu possa avvicinartici. Avere a disposizione
almeno qualcosa come DB_TREE di DB_File aiuterebbe. Se sei vincolato
all'uso di database .dbm, e questi non prevedono indici o altre strutture
di ordinamento dati, dovrai pensare a provvedere tu stesso qualche forma di
indicizzazione (banalmente, potresti mantenere un elenco ordinato in un
file di testo, aggiornandolo in background dopo ogni modifica al database).
Oppure potresti pensare di migliorare l'ordinamento in memoria, utilizzando
(se possibile) un algoritmo migliore del sort di perl o suddividendo il
database, in modo che ogni volta sia necessario ordinarne solo una parte, o
affidando gli ordinamenti parziali a più macchine, se ne puoi disporre.
Ovvero anche rassegnarti ai "disastrosi" 42 secondi, se ogni altra impresa
risulta troppo gravosa o comunque non conveniente rispetto ai vantaggi che
procurerebbe.
In breve, la risposta definitiva è politica, più che tecnica, e dipende dai
vincoli a cui devi sottostare.
Ciao.