Le migliori pratiche per ordinare, quindi invertire, o scrivere il comparatore "all'indietro"?

2

Ho scritto un comparatore per una mia classe personalizzata e quando ho eseguito il mio codice mi sono reso conto che l'output della mia lista di questi oggetti era nell'ordine inverso rispetto a quello che volevo. Era "ascendente" anziché "discendente". Questo perché mi sono attenuto alle specifiche di confronto in cui un valore di ritorno inferiore a 0 indica che l'altro oggetto è inferiore a questo e così via.

Per risolvere questo problema ho chiamato il metodo inverso sul mio elenco, ma avrei potuto anche cambiare il metodo di confronto in modo che ritorni maggiore di 0 dove l'altro oggetto è inferiore a questo.

Che cosa è visto come standard per questo caso e perché?

    
posta GKruger 07.05.2013 - 09:14
fonte

5 risposte

0

Inizia ignorando qualsiasi impatto sulle prestazioni di invertire la lista. Qualsiasi inversione sensibile dell'elenco sarà lineare nel tempo, il che significa che per le liste di grandi dimensioni, l'ordinamento sarà dominante.

Se esiste un ordinamento "naturale" dei tuoi elementi (ad esempio un ordinamento che è indipendente dalla tua particolare implementazione), ti consiglio di ordinare + reverse. Ciò renderà più facile il riutilizzo del comparatore e sarà più facile capire il codice che richiama l'ordinamento. Confronta questi due:

x = <array of integers>
x.sort(NaturalOrdering)
x.reverse

e

x = <array of integers>
x.sort(MyOrdering) // what ordering is this?

Se non esiste un ordinamento naturale (cioè imponi un ordinamento "artificiale" solo per poter ordinare gli elementi), probabilmente ha più senso che il comparatore restituisca direttamente l'ordine desiderato.

Se sei tentato di iniziare l'ottimizzazione a questo punto, misura il codice prima e dopo l'ottimizzazione. mai ovvio quale implementazione è la più veloce.

    
risposta data 07.05.2013 - 12:18
fonte
5

Il tuo vero problema è che stai usando il selezionatore sbagliato. Il tuo comparatore è corretto e (a seconda della lingua) potrebbe essere utilizzato per altri casi in cui il confronto non dovrebbe essere invertito. Invece di "aggiustare" (effettivamente interrompendo) il comparatore, dovresti scoprire come ottenere la selezionatrice in ordine decrescente. Qualsiasi libreria di ordinamento decente avrà questa opzione.

    
risposta data 07.05.2013 - 12:48
fonte
1

Utilizza il comparatore con l'ordine corretto per la tua applicazione. L'ordinamento e l'inversione significano che stai facendo l'ordinamento E che sta scorrendo di nuovo l'elenco per invertirlo.

Quando crei il comparatore, definisci il nuovo ordinamento e TU stai delimitando quale valore è minore e quale più alto. Per esempio. in ordine inverso di numeri naturali, 10 è inferiore a 9 anche se nel solito ordine ascendente 10 è maggiore di 9.

    
risposta data 07.05.2013 - 09:42
fonte
1

Se hai già scritto un comparatore, è ovviamente meglio modificarlo in modo che l'ordinamento standard (in ordine "crescente") faccia quello che vuoi.

La seconda cosa migliore è usare tutti gli switch o trucchi disponibili nei metodi di ordinamento standard della tua lingua. Come questo in Java:

Arrays.sort(array, Collections.reverseOrder());

La terza opzione, invertire una lista già ordinata, non è una soluzione categoricamente negativa. In alcuni casi è la soluzione più semplice e facile da comprendere. La maggior parte dell'efficienza di inversione di un array / elenco è trascurabile nella maggior parte dei casi.

    
risposta data 07.05.2013 - 10:46
fonte
1

Il confronto che lo rende ordinato nel giusto ordine è migliore. Quando usi già il comparatore (e lo fai in questo caso) è meglio (più veloce / più per libro) modificare il comparatore (o crearne un altro).

Sebbene, durante l'ordinamento di oggetti che hanno un confronto "naturale" (ad esempio: int) e "standard library" (ad esempio: BCL per .NET) che possono sfruttare ciò, potrebbe essere più rapido da ordinare in ordine naturale che inverso.

Ad esempio (C #), avente:

int[] data = new int[1000000];
Random rand = new Random();
for (int i = data.Length - 1; i >= 0; i--) data[i] = rand.Next();

l'ordinamento rispetto all'inversione:

Array.Sort(data);
Array.Reverse(data);

sarà necessario più veloce di:

Array.Sort(data, (a, b) => b.CompareTo(a));

Tuttavia non è il tuo caso, l'ho appena citato per completezza.

    
risposta data 07.05.2013 - 11:27
fonte

Leggi altre domande sui tag