Esercizio di comparazione

di il
17 risposte

Esercizio di comparazione

Buonasera a tutti, ho un problema con un esercizio da svolgere che richiede la modifica del codice di una classe aggiungendole la possibilità di essere comparabile secondo l'ordinamento naturale degli interi.
La classe inizia così:

public class MyArray
{
	private int[] a;
	public MyArray(int... interi) { a = interi; }
}

Io mi sono costruito una classe che mi funga da comparatore (pensando di darlo poi in pasto al metodo sort) solo che io qui non ho una lista bensì un array e non so come fare. Inoltre credo di aver costruito male il comparatore, perché l'ho fatto facendogli implementare l'interfaccia Comparator<Integer>. Non so davvero come svolgerlo...se qualcuno potesse aiutarmi ne sarei molto felice.
Grazie in anticipo

P.S. le mie conoscenze attuali si fermano alle lambda expressions

17 Risposte

  • Re: Esercizio di comparazione

    Shark95 ha scritto:


    La classe inizia così:
    
    public class MyArray
    {
    	private int[] a;
    	public MyArray(int... interi) { a = interi; }
    }
    
    
    L'array interno ad un oggetto MyArray deve essere ordinato ..... o N oggetti MyArray devono essere ordinati in base al loro contenuto?? Sono due cose ben differenti.

    Shark95 ha scritto:


    P.S. le mie conoscenze attuali si fermano alle lambda expressions
    Le lambda expression sono un concetto "avanzato" e recente. La comparazione degli oggetti viene molto ... molto prima.
  • Re: Esercizio di comparazione

    andbin ha scritto:


    Le lambda expression sono un concetto "avanzato" e recente. La comparazione degli oggetti viene molto ... molto prima.
    Non so dirti perché ma nel percorso che ho seguito le lambda e le interfacce funzionali sono state mostrate (decentemente) prima rispetto alle interfacce notevoli. Infatti mentre per le lambda e le Functional Interface sono riuscito a fare gli esercizi abbastanza tranquillamente, con le interfacce notevoli non ci sono ancora riuscito...forse perché ancora non ho capito
    Comunque ti cito il testo dell'esercizio, perché sinceramente non l'ho capito manco io se è l'array a dover essere ordinato oppure una lista di array:

    "Si modi?chi la seguente classe in modo da renderla comparabile secondo l’ordinamento naturale degli interi, apportando delle modi?che"
  • Re: Esercizio di comparazione

    Shark95 ha scritto:


    Non so dirti perché ma nel percorso che ho seguito le lambda e le interfacce funzionali sono state mostrate (decentemente) prima rispetto alle interfacce notevoli.
    Della serie: ti spieghiamo prima come funziona una Ferrari di F1 .... poi dopo magari una Punto.

    Shark95 ha scritto:


    Comunque ti cito il testo dell'esercizio, perché sinceramente non l'ho capito manco io se è l'array a dover essere ordinato oppure una lista di array:

    "Si modi?chi la seguente classe in modo da renderla comparabile secondo l’ordinamento naturale degli interi, apportando delle modi?che"
    Non è molto chiaro .... ma se di quella classe dice di "renderla comparabile", allora presupporrei che siano gli oggetti MyArray ad essere "comparabili" tra di loro (in base al loro array interno, chiaramente).

    Quindi vorrebbe dire: implementi Comparable in MyArray o implementi Comparator in una classe esterna.

    public class MyArray implements Comparable<MyArray>

    oppure

    public class ComparatoreMyArray implements Comparator<MyArray>

    e il compareTo() o compare() a seconda, avrà in mano 2 oggetti MyArray e dovrà dire se uno è minore/uguale/maggiore dell'altro. E in sostanza vuol dire alla fin fine confrontare due array, es. se {1, 4, 6} viene prima di {1, 5, 3}

    Sempre ammesso che sia quanto voluto ....
  • Re: Esercizio di comparazione

    Ok @andbin grazie mille, anche io penso che l'interpretazione sia questa....mi convince
    Prima di postare la domanda avevo creato una classe ComparatoreArray però ho sbagliato perché gli ho fatto implementare un Comparator<Integer>
    Quindi io se faccio implementare alla mia classe ComparatoreArray l'interfaccia Comparator<MyArray>, devo implementare il metodo che ritorna un intero chiamato compare(MyArray a1, MyArray a2) e fin qui ci siamo. Però in questo metodo devo richiamare un compareTo sui due oggetti MyArray? Se si, dove lo ridefinisco il compareTo?
    Ho studiato sui miei appunti la "teoria" sulle interfacce notevoli ma senza vedere qualche esercizio svolto per intero dubito di poter capire per questo sto cercando di fare questi esercizi...
  • Re: Esercizio di comparazione

    Shark95 ha scritto:


    se faccio implementare alla mia classe ComparatoreArray l'interfaccia Comparator<MyArray>, devo implementare il metodo che ritorna un intero chiamato compare(MyArray a1, MyArray a2)
    corretto.

    Shark95 ha scritto:


    Però in questo metodo devo richiamare un compareTo sui due oggetti MyArray? Se si, dove lo definisco il compareTo?
    Gli array non hanno un compareTo(), non implementano Comparable. Implementano solo due interfacce, dal Java Language Specification: "Every array type implements the interfaces Cloneable and java.io.Serializable."

    Questo ovviamente NON vuol dire che non sia fattibile.
    Soluzione fai-da-te: fai la comparazione "a mano" con del tuo codice. Confronti a[0] con b[0], se uno dei due è minore o maggiore, hai GIA' il risultato, non devi procedere oltre. Se invece sono uguali, procedi a confrontare i due [1] e così via. Serve un ciclo, chiaramente.
    Se ad un certo punto mancano elementi ... lo devi capire tu (non devi sforare e causare eccezioni). A quel punto decidi tu ma per logica {1,2} viene prima di {1,2,3} .

    Altrimenti si cerca una libreria che abbia un metodo di utilità già fatto per il confronto. Che però forse non è valido ai fini di un esercizio.
  • Re: Esercizio di comparazione

    Grazie andbin ma stasera ho le idee un po' confuse, nel frattempo avevo fatto la comparazione a mano creandomi un metodo compareTo nella classe MyArray però mi rendo conto che non ha senso...credo che per oggi sia abbastanza e quindi ci dormo su
    Domani appena mi sveglio cerco di capire come fare seguendo i tuoi consigli...al momento non ragiono più <_<
  • Re: Esercizio di comparazione

    andbin ha scritto:


    Soluzione fai-da-te: fai la comparazione "a mano" con del tuo codice.
    Buongiorno andbin, forse ce l'ho fatta. Potresti dare una controllata al mio codice?
    Comunque ho provato in alternativa a scrivere un metodo int compareTo(MyArray b) all'interno di MyArray per poi farlo richiamare dal metodo compare che si trova nella classe MyArray. In questo modo è come se avessi reso comparabile l'array giusto? O devo fargli implementare l'interfaccia comparable? Nel senso, io so che se non gli faccio implementare l'interfaccia comparable, allora non sto dichiarando che la mia classe MyArray è comparabile...però mi domando che differenza ci sia a questo punto, se io scrivessi direttamente un metodo compareTo anzichè fargli implementare l'interfaccia. Ovviamente il metodo compareTo avrei potuto chiamarlo in qualsiasi altro modo...però ho reso o no comparabile MyArray?

    Comunque dimentica per un attimo quello che ho detto nel capoverso precedente e se puoi, dai un'occhiata al codice FINALE di questo piccolo esercizio e dimmi se va bene o come può essere migliorato o ottimizzato.
    Ecco qui il codice:
    
    package MyArrayComparable;
    
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    
    public class MyArray 
    {
    	private int a[];
    	
    	public MyArray(int...interi) { a = interi; }
    	
    	public int[] getArray() { return a; }
    	public int length() { return a.length; }
    	
    		
    }
    
    
    package MyArrayComparable;
    
    import java.util.Arrays;
    import java.util.Comparator;
    
    public class ComparatoreArray implements Comparator<MyArray>
    {
    	@Override
    	public int compare(MyArray a, MyArray b)
    	{
    		/*
    		 * Sostanzialmente aggiunge degli zeri all'array più piccolo
    		 * in modo tale che quando verrà eseguito il confronto, tutti gli elementi 
    		 * verranno confrontati 
    		 */ 
    		int lung1 = a.getArray().length;
    		int lung2 = b.getArray().length;
    		int[] copiaArray1 = Arrays.copyOf(a.getArray(),lung1);
    		int[] copiaArray2 = Arrays.copyOf(b.getArray(),lung2);
    		if (lung1 < lung2) { copiaArray1 = Arrays.copyOf(copiaArray1, lung1+lung2-lung1); }
    		else if (lung1 > lung2) { copiaArray2 = Arrays.copyOf(copiaArray2, lung2+lung1-lung2);}
    		 
    		/*
    		 * Esegue un ciclo per confrontare ogni elemento del primo
    		 * array con il corrispondente elemento del secondo array
    		 */
    		int valore = 0;
    		for (int i=0; i<copiaArray1.length; i++)
    		{
    			int intero1 = copiaArray1[i];
    			int intero2 = copiaArray2[i];
    			if (intero1 > intero2) { return 1; }
    			else if (intero1 < intero2) { return -1; }
    		}
    		return valore;
    	}
    }
    
    Ti ringrazio in anticipo buona giornata
  • Re: Esercizio di comparazione

    Shark95 ha scritto:


    Comunque ho provato in alternativa a scrivere un metodo int compareTo(MyArray b) all'interno di MyArray per poi farlo richiamare dal metodo compare che si trova nella classe MyArray. In questo modo è come se avessi reso comparabile l'array giusto? O devo fargli implementare l'interfaccia comparable? Nel senso, io so che se non gli faccio implementare l'interfaccia comparable, allora non sto dichiarando che la mia classe MyArray è comparabile...però mi domando che differenza ci sia a questo punto, se io scrivessi direttamente un metodo compareTo anzichè fargli implementare l'interfaccia. Ovviamente il metodo compareTo avrei potuto chiamarlo in qualsiasi altro modo...però ho reso o no comparabile MyArray?
    Troppa confusione!!

    La differenza concettuale tra Comparable e Comparator è abbastanza semplice: Comparable si implementa NELLA classe degli oggetti da confrontare. Pertanto ci può essere UN SOLO criterio con Comparable e, da specifiche Java, in teoria dovrebbe rappresentare l'ordinamento "naturale" di quei oggetti (perlomeno quello più tipico/logico).

    Comparator si implementa in classi DISTINTE da quella degli oggetti da confrontare. Pertanto di criteri di ordinamento con Comparator ne puoi avere quanti ne vuoi.

    Tieni presente che quanto hai citato all'inizio dice: "richiede la modifica del codice di una classe aggiungendole la possibilità di essere comparabile".
    E questo porta a pensare che sia MyArray a dover diventare Comparable<MyArray> .

    Shark95 ha scritto:


    	@Override
    	public int compare(MyArray a, MyArray b)
    	{
    		/*
    		 * Sostanzialmente aggiunge degli zeri all'array più piccolo
    		 * in modo tale che quando verrà eseguito il confronto, tutti gli elementi 
    		 * verranno confrontati 
    		 */ 
    		int lung1 = a.getArray().length;
    		int lung2 = b.getArray().length;
    		int[] copiaArray1 = Arrays.copyOf(a.getArray(),lung1);
    		int[] copiaArray2 = Arrays.copyOf(b.getArray(),lung2);
    		if (lung1 < lung2) { copiaArray1 = Arrays.copyOf(copiaArray1, lung1+lung2-lung1); }
    		else if (lung1 > lung2) { copiaArray2 = Arrays.copyOf(copiaArray2, lung2+lung1-lung2);}
    		 
    		/*
    		 * Esegue un ciclo per confrontare ogni elemento del primo
    		 * array con il corrispondente elemento del secondo array
    		 */
    		int valore = 0;
    		for (int i=0; i<copiaArray1.length; i++)
    		{
    			int intero1 = copiaArray1[i];
    			int intero2 = copiaArray2[i];
    			if (intero1 > intero2) { return 1; }
    			else if (intero1 < intero2) { return -1; }
    		}
    		return valore;
    	}
    }
    
    Questa comparazione (anche se tecnicamente funzionasse al 100%) è assolutamente lunga, "contorta" e "pesante". Non servono tutti questi ragionamenti su copie, zeri, lunghezze.
    Serve solo "ragionare" un pochino meglio.
  • Re: Esercizio di comparazione

    andbin ha scritto:


    Questa comparazione (anche se tecnicamente funzionasse al 100%) è assolutamente lunga, "contorta" e "pesante"
    Lo so andbin ma non sono esperto...quindi non so come migliorare il codice. Comunque a funzionare funziona, almeno per i test che ho fatto io. Il codice inizialmente era molto molto semplice ma poi quando mi hai fatto notare che se io ho [0,9] e [0,9,2] dovrebbe venire prima [0,9] ho adottato le poche tecniche che conosco ed è venuto fuori questo. Lo so che è poco leggibile ma non conosco un modo migliore per farlo. Del resto ho iniziato da poco a programmare.
    Puoi suggerirmi qualche idea?
  • Re: Esercizio di comparazione

    Shark95 ha scritto:


    ma non conosco un modo migliore per farlo.
    Puoi suggerirmi qualche idea?
    Assegna i due array a due variabili (per non ripetere il getArray() molte volte, chiaramente).
    Determina la lunghezza "minima" dei due array (puoi usare Math.min() ).
    Fai un ciclo con una i da 0 per minore di questa lunghezza minima. Essendo quella minima, i valori ci sono tutti per entrambi gli array. Compara gli elementi i-esimi, se uno dei due è minore o maggiore dell'altro hai GIA' il risultato (non devi proseguire). Se sono uguali, non fai nulla (il ciclo prosegue).

    Terminato il ciclo hai solamente 3 scenari da valutare:
    - a è più corto di b
    - a è più lungo di b
    - a e b sono lunghi uguali (e siccome il ciclo for non ha evidenziato differenze, allora gli array sono davvero uguali).
  • Re: Esercizio di comparazione

    Buongiorno @andbin perdona il mio ritardo nel rispondere.

    andbin ha scritto:


    Assegna i due array a due variabili (per non ripetere il getArray() molte volte, chiaramente).
    Determina la lunghezza "minima" dei due array (puoi usare Math.min() ).
    Fai un ciclo con una i da 0 per minore di questa lunghezza minima. Essendo quella minima, i valori ci sono tutti per entrambi gli array. Compara gli elementi i-esimi, se uno dei due è minore o maggiore dell'altro hai GIA' il risultato (non devi proseguire). Se sono uguali, non fai nulla (il ciclo prosegue).
    Io avevo fatto esattamente così inizialmente, ma poi mi sono accorto (come ti dicevo in precedenza) che se io ho due array (uso le quadre per semplicità) [0,9,2] e [0,9], deve venire prima [0,9] e poi [0,9,2] come giustamente mi hai fatto notare, ma con un codice scritto con quella logica ho constatato che il risultato non è quello che ci si aspetta. Perché per esempio, se provo a mettere (nella List<MyArray>) i seguenti array in questo ordine:

    [4,5,2]
    [1,5,2]
    [0,6,2]
    [0,5,7]
    [0,9,2]
    [0,9]

    L'output generato dall'algoritmo è questo:

    [0,5,7] giusto...
    [0,6,2] giusto...
    [0,9,2] sbagliato...no?
    [0,9] sbagliato...no?
    [1,5,2] giusto...
    [4,5,2] giusto...

    Se invece nella List<MyArray > mettessi prima [0,9] e poi [0,9,2] allora l'output sarebbe esatto. Perché in effetti ragionandoci, credo che il metodo sort vada a prendere in questo caso prima [0,9] confrontandolo poi con [0,9,2] e il metodo compare ritornando 0, fa si che non venga spostato niente nella lista per quel particolare processo.

    Quindi come posso risolvere snellendo il mio codice che aggiunge zeri o modificandolo completamente? Ti ringrazio in anticipo
  • Re: Esercizio di comparazione

    Shark95 ha scritto:


    ma con un codice scritto con quella logica ho constatato che il risultato non è quello che ci si aspetta.
    Ti assicuro che come ho indicato io è e viene corretto.

    Posta il codice, così vediamo.
  • Re: Esercizio di comparazione

    andbin ha scritto:


    Ti assicuro che come ho indicato io è e viene corretto.
    Allora sicuramente ho sbagliato qualcosa nella logica del metodo
    Ti posto il codice che avevo scritto inizialmente:
    
    	@Override
    	public int compare(MyArray a, MyArray b)
    	{
    		int[] array1 = a.getArray();
    		int[] array2 = b.getArray();
    		int valore = 0;
    		
    		int min = Math.min(array1.length,array2.length);
    		
    		for (int i=0; i<min; i++)
    		{
    			if (array1[i] > array2[i]) { valore++; break; }
    			else if (array1[i] < array2[i]) { valore--; break; }
    		}
    		
    		return valore;
    	}
    
  • Re: Esercizio di comparazione

    Shark95 ha scritto:


    Allora sicuramente ho sbagliato qualcosa nella logica del metodo
    Infatti quello che hai scritto è incompleto/insensato. Quei valore++ e valore-- non hanno senso (cioè non si fa così, normalmente) e non hai nemmeno contemplato tutti gli scenari che ho citato io.

    Rileggi quanto ho scritto prima. Ora vado a pranzo e vediamo più tardi.
Devi accedere o registrarti per scrivere nel forum
17 risposte