PDA

View Full Version : [JAVA] Ordinare array secondo "qualcosa" e Arrays.sort


cdere
08-05-2010, 15:13
Salve a tutti :)
Ho questo problemino... ho questo algoritmo di quicksort (che funziona e anche bene) perchè ordini un array di "tuple" (sostanzialmente una matrice) in base al nome della "colonna" (cioè in base ai valori che sono in 'attributo' che è la colonna di questa matrice non in base a tutti i valori)

vi posto la "matrice" (in realtà un'array di classe Tupla) e l'algoritmo:

data = new Tuple[14];

/* D1 */ data[0] = new Tuple( "Sunny","Hot","High","Weak","No" );

in corrispondenza di ogni valore di tupla chiaramente c'è un attributo, io con tale algoritmo ordino l'array in base all'attributo che voglio

void sort(Attribute attribute, int beginExampleIndex, int endExampleIndex){
quicksort(attribute, beginExampleIndex, endExampleIndex);
}


// scambio esempio i con esempio j
private void swap(int i,int j){
Object temp;
for (int k=0; k<getNumberOfExplanatoryAttributes()+1; k++){
temp = data[i].getValue(k);
data[i].setValue(k, data[j].getValue(k) );
data[j].setValue(k, temp);
}
}


/*
* Partiziona il vettore rispetto all'elemento x e restiutisce il punto di separazione
*/
private int partition(DiscreteAttribute attribute, int inf, int sup){
int i, j;
i=inf;
j=sup;
int med = (inf+sup)/2;
String x = (String)getExplanatoryValue(med, attribute.getIndex());
swap(inf, med);
while (true){
while(i<=sup && ((String)getExplanatoryValue(i, attribute.getIndex())).compareTo(x)<=0)
i++;
while(((String)getExplanatoryValue(j, attribute.getIndex())).compareTo(x)>0)
j--;
if(i<j)
swap(i,j);
else break;
}
swap(inf,j);
return j;
}


/*
* Algoritmo quicksort per l'ordinamento di un array di interi A
* usando come relazione d'ordine totale "<="
* @param A
*/
private void quicksort(Attribute attribute, int inf, int sup){
if(sup >= inf){
int pos;
pos = partition((DiscreteAttribute)attribute, inf, sup);
if ((pos-inf) < (sup-pos+1)) {
quicksort(attribute, inf, pos-1);
quicksort(attribute, pos+1, sup);
}
else
{
quicksort(attribute, pos+1, sup);
quicksort(attribute, inf, pos-1);
}
}
}

ok.. ora però mi sembra un po inutile reimplementare un algoritmo di sort.. quindi avevo pensato di utilizzare Arrays.sort (e implementare una delle 2 interfacce comparator o comparable)... solo che solo che... come faccio a "passargli" anche il nome dell'attributo per il quale deve ordinare i valori?


Grazie mille ragazzi!
siete grandi :)

PGI-Bis
08-05-2010, 15:43
Puoi usare il sort di Arrays che accetta come secondo argomento un Comparator<T> dove T è il tipo di componenti dell'array (se sono stringhe sarà string, se sono tuple sarà tuple). Il comparator ha un metodo ad hoc (compare) attraverso il quale stabilisci la tua relazione d'ordine.

cdere
08-05-2010, 16:36
tu parli giustamente di questo (perchè a me servono anche gli estremi degli indici):
public static <T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)

ma non so come chiamarlo:

Comparator<Tuple[]> c = null;
Arrays.sort(data, beginExampleIndex, endExampleIndex, c);

data è il mio array di Tuple, invece per comparator non so proprio cosa mettere! bho non capisco proprio il senso.

EDIT: ma posso passare una stringa a Compare? (cioè il nome dell'attributo per quale voglio ordinare) e se si, come ?

PGI-Bis
08-05-2010, 16:49
Comparator è un'interfaccia, devi creare una classe che la implementi. Puoi usare la forma anonima o no. Di solito se una certa definizione appare una sola volta nel programma, in ragione di certe sue particolarità, si usa una classe anonima. Diciamo che la tua classe Tuple è questa:

public class Tuple {
private final String[] data;

public Tuple(String[] data) {
this.data = data;
}

public String[] getData() {
return data;
}
}

Crei la tua classettina che concretizza un Comparator<Tuple>:

import java.util.Comparator;

public class TupleComparable implements Comparator<Tuple> {

public int compare(Tuple o1, Tuple o2) {

}

}

Secondo il contratto di Comparator, il metodo compare deve restituire un numero minore di zero se o1 è minore di o2, zero se o1 è uguale a o2, un numero maggiore di 1 se o1 è maggiore di o2.

Mi pare vagamente di capire che l'ordine dipenda dall'indice del componente dell'array di tuple. Puoi dire una cosa del genere:

import java.util.Comparator;

public class TupleComparable implements Comparator<Tuple> {

private final int componentIndex;

public TupleComparable(int componentIndex) {
this.componentIndex = componentIndex;
}

public int compare(Tuple o1, Tuple o2) {
return o1.getData()[componentIndex].compareTo(o2.getData()[componentIndex]);
}

}

Qui che succede? Succede che un certo TupleComparable confronta due Tuple usando la stringa in una certa posizione. A questo punto dato un array di Tuple:

Tuple[] elementi = qualcosa

ordini l'array dicendo:

Arrays.sort(elementi, new TupleComparable(0));

o new TupleComparable(1), come vuoi.

cdere
08-05-2010, 17:49
:ave: :ave: :ave: :ave: :ave:
grazie mille PGI-Bis sei stato davvero disponibilissimo, chiaro ed esauriente.
Non avrei potuto chiedere di più!

Infatti il "robo" :D funziona!
public class TupleComparator implements Comparator<Tuple>{

private int index;

public TupleComparator(Attribute attribute) {
index = attribute.getIndex();
}


@Override
public int compare(Tuple rec1, Tuple rec2) {
return ((String)rec1.getValue(index)).compareTo( (String)rec2.getValue(index) );
}

}

Però, però... c'è un però... non so perchè, ma ogni ordinamento che effettua, l'ultima tupla non è ordinata, non so perchè, sempre l'ultima non c'entra nulla...

so che praticamente non ho detto niente, ma magari è un problema "comune" in questi casi, idee?

EDIT: c'era un -1 all'endIndex.. che dire risolto, GRAZIE :D

WarDuck
08-05-2010, 18:11
Si può fare anche così, senza creare un'altra classe:

class Tupla implements Comparable<Test>
{

...
attributi di classe
...

...
metodi di classe
...

public int compareTo(Test o) {
// ritorna -1, 0, 1 a seconda dei casi
}
}

A questo punto poi:


Tupla[] arr = new Tupla[] { ... };

Arrays.sort(arr);


Personalmente lo trovo un po' più elegante (ammesso cmq che si abbia accesso ai sorgenti della classe Tupla) :p.

cdere
08-05-2010, 18:13
o non ho capito io, o tu non hai letto la discussione :confused: io con TupleComparator ordino data (ricordo array di tuple) secondo l'attributo (tipo l'ORDER BY di SQL) (che passo al costruttore di TupleComparator) tu ordini e basta :confused:

WarDuck
08-05-2010, 18:15
o non ho capito io, o tu non hai letto la discussione :confused: io con TupleComparator ordino data (ricordo array di tuple) secondo l'attributo (tipo l'ORDER BY di SQL) (che passo al costruttore di TupleComparator) tu ordini e basta :confused:

Forse ho letto male io :D.

cdere
08-05-2010, 18:22
ok ok figurati :D