PDA

View Full Version : [Java] iterazione "doppia"


71104
29-06-2008, 16:42
tramite una LinkedList vorrei realizzare un algoritmo banalissimo, una doppia iterazione su tutta la lista (come due for annidati in poche parole), ma non ci riesco perché le iterazioni prevedono la cancellazione occasionale di coppie di elementi :mc:

praticamente dovrei realizzare un algoritmo come quello che scrivo di seguito in pseudocodice:

# L è una lista doppiamente linkata
for each A in L
for each B in L
if (A != B) AND <some other conditions>
L <- L \ {A U B} # rimuovi sia A che B


secondo voi è fattibili in Java tramite LinkedList e iteratori? :help:
ho persino provato a reimplementare una mia AbstractSequentialList ma ho desistito presto: è troppo difficile da implementare perché è inutilmente complessa a causa di quell'idiotissimo sistema di indici che fa parte dell'interfaccia Collection :muro:

^TiGeRShArK^
29-06-2008, 19:51
ma se scorri la lista al contrario non risolvi?:fagiano:

71104
29-06-2008, 20:05
ma se scorri la lista al contrario non risolvi?:fagiano: non vedo perché dovrei... :fagiano:
mi fai un esempio? :help:

DanieleC88
29-06-2008, 20:08
ma se scorri la lista al contrario non risolvi?:fagiano:
Uhm, se non ho capito male, scorrendo gli elementi A dall'inizio alla fine, e scorrendo gli elementi B dalla fine all'inizio? Potrebbe funzionare... :D

^TiGeRShArK^
29-06-2008, 20:09
Uhm, se non ho capito male, scorrendo gli elementi A dall'inizio alla fine, e scorrendo gli elementi B dalla fine all'inizio? Potrebbe funzionare... :D
in java che io sappia è l'unico modo per cancellare degli elementi in una lista durante un'iterazione, e per me ha sempre funzionato.. :fagiano:

EDIT: o meglio è il modo + semplice.
Un altro modo potrebbe essere quello di memorizzarsi gli indici degli elementi da eliminare ed eliminarli subito dopo la fine dell'iterazione.

71104
29-06-2008, 20:38
ma se io modifico la lista tramite un altro iterator (quello che uso per cancellare gli elementi B) non dovrebbe venir lanciata una ConcurrentModificationException?

e poi non ho capito perché, usando due iteratori, col secondo dovrei andare dalla fine verso l'inizio :fagiano:

feboss
29-06-2008, 20:44
in pratica devi scorrere la lista e cancellare tutti gli element che si ripetono?

wingman87
29-06-2008, 21:00
# L è una lista doppiamente linkata
for each A in L
for each B in L
if (A != B) AND <some other conditions>
L <- L \ {A U B} # rimuovi sia A che B


Non ho ben capito il problema, l'unica cosa che mi viene in mente è che in questo pseudocodice che hai scritto probabilmente manca un break dopo la cancellazione della coppia di elementi.
Per il resto, perché non dovrebbe funzionare? Dov'è il problema anche se cancelli qualche elemento?

k0nt3
29-06-2008, 21:01
non puoi banalmente fare:

for (Object a : list) {
for (Object b : list) {
if(whatever) {
Object[] toRemove = {a, b};
list.remove(toRemove);
}
}
}

feboss
29-06-2008, 21:12
non puoi banalmente fare:

for (Object a : list) {
for (Object b : list) {
if(whatever) {
Object[] toRemove = {a, b};
list.remove(toRemove);
}
}
}

Mi piace questo codice.Potresti per favore spiegarmi ogni istruzione?
perchè mi interessa particolarmente.se è possibile anche trasformando quel for, in un for normale
Tranne l'ultimo pezzo
Object[] toRemove = {a, b};
list.remove(toRemove);
grazie

k0nt3
29-06-2008, 21:43
Mi piace questo codice.Potresti per favore spiegarmi ogni istruzione?
perchè mi interessa particolarmente.se è possibile anche trasformando quel for, in un for normale
Tranne l'ultimo pezzo
Object[] toRemove = {a, b};
list.remove(toRemove);
grazie

niente si traduce con: per ogni oggetto a in list fai ecc... in questo modo la creazione dell'iteratore è implicita (funziona da java5 in poi)
potresti scriverlo così:

for (Iterator i1 = list.iterator(); i1.hasNext();) {
Object a = (Object) i1.next();
for (Iterator i2 = list.iterator(); i2.hasNext();) {
Object b = (Object) i2.next();
if(...) {
Object[] toRemove = {a, b};
list.remove(toRemove);
}
}
}

^TiGeRShArK^
29-06-2008, 22:20
no, attenzione.
Con il metodo della cancellazione immediata senza memorizzazione degli indici degli oggetti da rimuovere non si può utilizzare un iteratore, ma bisogna scorrere la lista al contrario, e mi sembrava ovvio e scontato che l'unico modo per fare questo è utilizzando un ciclo for che parta dalla fine e decrementi l'indice di uno fino ad arrivare a zero.
Per la memorizzazione degli indici invece si può utilizzare la struttura che si preferisce per iterare sulla lista perchè tanto la cancellazione avviene solo in un momento successivo iterando sulla lista degli elementi da cancellare e eliminandoli dall'altra lista.

^TiGeRShArK^
29-06-2008, 22:24
tradotto in codice:

for (int i = lista.size() - 1; i >= 0; i--) {
for (int j = lista.size() - 1; j >= 0; j--) {
if (condition) {
lista.remove(i);
lista.remove(j);
}
}
}

^TiGeRShArK^
29-06-2008, 22:48
mmmm..
ora che ci penso con l'iterazione doppia non l'ho mai provata..
vabbè..
in caso non dovesse andare puoi sempre memorizzarti in una lista gli indici (o gli oggetti) da rimuovere e dopo aver finito l'iterazione iteri questa lista e li elimini dalla lista originaria.

DanieleC88
29-06-2008, 23:36
[...]
if (condition) {
lista.remove(i);
lista.remove(j);
}
[...]
Uhm, però così dovresti fare uno step su i ad ogni rimozione (altrimenti, dopo la prima, lista.remove(i) cosa va a rimuovere?), almeno ad occhio mi pare così.

DanieleC88
29-06-2008, 23:37
for (int i = lista.size() - 1; i >= 0; i--) {
bool found = false;

for (int j = lista.size() - 1; j >= 0; j--) {
if (condition) {
lista.remove(j);
found = true;
}
}

if (found) {
lista.remove(i);
}
}


Una cosa del genere? :boh:

banryu79
30-06-2008, 08:22
for (int i = lista.size() - 1; i >= 0; i--) {
bool found = false;

for (int j = lista.size() - 1; j >= 0; j--) {
if (condition) {
lista.remove(j);
found = true;
}
}

if (found) {
lista.remove(i);
}
}


Una cosa del genere? :boh:

Va bene solo se l'elemento j-esimo è sempre successivo all'elemento i-esimo; in caso contrario l'ultima istruzione (lista.remove(i)) opera su un indice *non più valido* [perchè prima verrebbe eseguito lista.remove[j] e se j precede i non va bene]
Ciò dipende dalla logica espressa in "if(condition)"...


La soluzione per me è iterare la lista linkata con tutti gli Iterator che si ritiene necessario per raccogliere in un'altra Collection gli indici degli elementi da rimuovere e rimuovere tutto alla fine, a parte.

Certo per valutare se la cosa è possibile e non porta via troppo tempo sarebbe utile sapere prima a cosa serve la lista linkata nel programma e che dimensioni può avere.

71104
30-06-2008, 09:25
in pratica devi scorrere la lista e cancellare tutti gli element che si ripetono? non proprio in verità, comunque si, per semplificare potremmo dire che devo cancellare una coppia di elementi (A, B), con A che precede B, se (A != B) && (A.equals(B))



# L è una lista doppiamente linkata
for each A in L
for each B in L
if (A != B) AND <some other conditions>
L <- L \ {A U B} # rimuovi sia A che B


Non ho ben capito il problema, l'unica cosa che mi viene in mente è che in questo pseudocodice che hai scritto probabilmente manca un break dopo la cancellazione della coppia di elementi. uh? no, dopo averli cancellati devo andare avanti e vedere se ci sono altre coppie da cancellare.


Per il resto, perché non dovrebbe funzionare? Dov'è il problema anche se cancelli qualche elemento? ConcurrentModificationException :fagiano:


non puoi banalmente fare:

for (Object a : list) {
for (Object b : list) {
if(whatever) {
Object[] toRemove = {a, b};
list.remove(toRemove);
}
}
}
ConcurrentModificationException :fagiano:

71104
30-06-2008, 09:33
no, attenzione.
Con il metodo della cancellazione immediata senza memorizzazione degli indici degli oggetti da rimuovere non si può utilizzare un iteratore, ma bisogna scorrere la lista al contrario, e mi sembrava ovvio e scontato che l'unico modo per fare questo è utilizzando un ciclo for che parta dalla fine e decrementi l'indice di uno fino ad arrivare a zero.
Per la memorizzazione degli indici invece si può utilizzare la struttura che si preferisce per iterare sulla lista perchè tanto la cancellazione avviene solo in un momento successivo iterando sulla lista degli elementi da cancellare e eliminandoli dall'altra lista. usare il sistema degli indici è una cosa che vorrei evitare: è un sistema totalmente idiota che trasforma l'operazione di cancellazione da una lista da O(1) a O(N) :fagiano:
non mi capacito di come sia possibile che gli autori del Collection Framework abbiano avuto un'idea così cretina :fagiano:

al limite piuttosto che cancellare per indice preferirei flaggare gli elementi da cancellare e fare quindi una cosa del genere:

LinkedList<MyItem> originalList;

.
.
.

class ItemContainer
{
public MyItem item;
public boolean delete = false;

public ItemContainer(MyItem item)
{
this.item = item;
}

}

.
.
.

LinkedList<ItemContainer> copiedList = new LinkedList<ItemContainer>();
for (MyItem item : originalList)
{
copiedList.add(new ItemContainer(item));
}

for (ItemContainer A : copiedList)
{
for (ItemContainer B : copiedList)
{
if ((A != B) && (<some other conditions>))
{
A.delete = true;
B.delete = true;
}
}
}

Iterator<ItemContainer> i = copiedList.iterator();
while (i.hasNext())
{
if (i.next().delete)
{
i.remove();
}
}

originalList.clear();
for (ItemContainer container : copiedList)
{
originalList.add(container.item);
}


ma sinceramente mi sembra scandaloso, speravo in qualcosa di molto più semplice :muro:

71104
30-06-2008, 09:36
una condizione che forse può aiutare a risolvere il problema (anche se credo che non ci sia soluzione :muro: ) è che se esiste una coppia (A, B) di elementi da cancellare allora A nella lista precede B, e quindi l'iterazione interna non ha bisogno di esaminare anche tutti gli elementi che precedono A, ma può partire dal successore.

71104
30-06-2008, 09:39
for (int i = lista.size() - 1; i >= 0; i--) {
bool found = false;

for (int j = lista.size() - 1; j >= 0; j--) {
if (condition) {
lista.remove(j);
found = true;
}
}

if (found) {
lista.remove(i);
}
}


Una cosa del genere? :boh: vorrei evitare gli indici sulla lista :cry:
comunque si, in teoria credo che quello funzioni e che sia anche l'unica soluzione semplice -.-'

k0nt3
30-06-2008, 10:13
uhm credo di aver capito :fagiano:
IMHO è meglio mettere in una lista gli elementi da rimuovere e farlo in un secondo momento

VICIUS
30-06-2008, 10:27
Puoi ordinare la lista? Se si poi diventa banale eliminare tutti i doppioni visto che sono tutti vicini tra loro.

71104
30-06-2008, 10:30
intanto volevo rettificare una cosa scandalosa che mi sono accorto di aver scritto nello pseudocodice del primo post, stravolgendo la teoria degli insiemi :D


# L è una lista doppiamente linkata
for each A in L
for each B in L
if (A != B) AND <some other conditions>
L <- L \ {A U B} # rimuovi sia A che B


volevo dire:

{A} U {B}

oppure

{A, B}


:fagiano:

71104
30-06-2008, 10:33
Puoi ordinare la lista? Se si poi diventa banale eliminare tutti i doppioni visto che sono tutti vicini tra loro. veramente non vedo la banalità :fagiano:
l'impedimento della ConcurrentModificationException c'è sempre :muro:
ed inoltre se ordinassi la lista dovrei crearne una copia, perché l'originale preferirei che fosse nell'ordine iniziale; non che sia un problema, anzi se Java mi offre qualche metodo che mi permette di ordinare una lista in base ad un criterio stabilito da me risulterebbe fattibile, eccezione a parte.

gugoXX
30-06-2008, 10:40
Usare una lista di appoggio contenente le future cancellazioni?
Io solitamente faccio cosi'


# D e' una lista vuota.
# L è una lista doppiamente linkata
for each A in L
if A in D then continue
for each B in L
if B in D then continue
if (A != B) AND <some other conditions>
Push A, B in D

Remove from L all D


Poi a dire il vero utilizzo una hastable invece che una lista, per gli elementi da cancellare, cosi' la ricerca "Contains" e' O(1).


Piu' gli elementi da cancellare sono tanti (rispetto alla totalita'), meno questo metodo e' efficiente.
Comunque sei sicuro che ti serva un ciclo del genere?
Solitamente per il ciclo interno e' sufficiente partire dall'elemento successivo a quello corrente del ciclo esterno, per avere una e una sola volta ogni possibile coppia di elementi, senza ripetizione.

Edit. Ho visto che era gia' stata suggerita da K0nt3. Scusa.

banryu79
30-06-2008, 11:02
...anzi se Java mi offre qualche metodo che mi permette di ordinare una lista in base ad un criterio stabilito da me risulterebbe fattibile, eccezione a parte.

Dovresti "sporcarti le mani" con l'interfaccia Comparable e il suo metodo compareTo() oppure l'interfaccia Comparator<T>: in entrambi i casi si tratta poi di usare uno dei metodi .sort(...) della classe Collections.

VICIUS
30-06-2008, 11:17
veramente non vedo la banalità :fagiano:
l'impedimento della ConcurrentModificationException c'è sempre :muro:
ed inoltre se ordinassi la lista dovrei crearne una copia, perché l'originale preferirei che fosse nell'ordine iniziale; non che sia un problema, anzi se Java mi offre qualche metodo che mi permette di ordinare una lista in base ad un criterio stabilito da me risulterebbe fattibile, eccezione a parte.
Se la lista è ordinata basta un ciclo solo per eliminare tutti i duplicati. Qualcosa tipo questo:
for (int i = 0; i < lista.count() - 1; )
{
if (lista[i] == lista[i+1])
{
lista.remove(i+1);
}
else
{
++i;
}
}

71104
30-06-2008, 11:52
uhm, effettivamente credo di potermela cavare ordinando la lista con un criterio stabilito da me (grazie per le indicazioni banryu :)), poi a pensarci bene gli elementi simili potrei anche rimuoverli con l'iteratore.

grazie a tutti, vi farò sapere :D

^TiGeRShArK^
30-06-2008, 12:10
con l'ordinamento è banale, perchè se scorri la lista al contrario basta fare qualcosa del genere:

for (int i = orderedList.size() - 1; i > 0; i--) {
if (orderedList(i) == orderedList(i - 1)) {
orderedList.remove(i);
}
}

Comunque sei sicuro che la lista sia una buona soluzione nel tuo caso?
Ogni volta che rimuovi un elemento tutti gli elementi successivi vengono shiftati di uno.... :fagiano:
Imho vedrei meglio una HashMap anche se non ho ancora ben capito a cosa ti serve..
In + nella hashmap elimini il problema degli elementi uguali dato che nella stessa chiave ci può stare un solo valore...

71104
30-06-2008, 13:31
Comunque sei sicuro che la lista sia una buona soluzione nel tuo caso?
Ogni volta che rimuovi un elemento tutti gli elementi successivi vengono shiftati di uno.... :fagiano: stiamo parlando di LinkedList, non di ArrayList :fagiano:

l'inserimento e la rimozione di un elemento da una lista linkata sono operazioni O(1).


Imho vedrei meglio una HashMap anche se non ho ancora ben capito a cosa ti serve..
In + nella hashmap elimini il problema degli elementi uguali dato che nella stessa chiave ci può stare un solo valore... il problema è che io devo avere elementi uguali nella stessa lista: quelli che devo eliminare non sono precisamente i doppioni, come avevo detto approssimativamente qualche post fa, ma gli elementi che risultano simili secondo un certo mio criterio.

inoltre la HashMap non è ordinata, mentre la lista linkata si; a me serve una collezione ordinata (l'ordine di restituzione degli elementi deve rimanere coerente da un'iterazione all'altra).

edit - tra l'altro più che la HashMap sarebbe meglio un HashSet visto che non ho chiavi ma solo valori, ma un insieme non va bene perché gli insiemi non contengono doppioni.

banryu79
30-06-2008, 15:55
uhm, effettivamente credo di potermela cavare ordinando la lista con un criterio stabilito da me (grazie per le indicazioni banryu :)), poi a pensarci bene gli elementi simili potrei anche rimuoverli con l'iteratore.

grazie a tutti, vi farò sapere :D
Figurati, tengo alta la bandiera Java! :sofico:

gugoXX
30-06-2008, 16:32
Figurati, tengo alta la bandiera Java! :sofico:

E fai bene... ce n'e' bisogno. :tapiro: :tapiro: (Scherzo)


var Result = from valore in Lista
group valore by valore into gruppo
where gruppo.Count()==1
select gruppo.Key;

foreach (int y in Result)
{
Console.WriteLine(y);
}


PS, sto usando Java proprio in questo momento.

^TiGeRShArK^
30-06-2008, 16:34
E fai bene... ce n'e' bisogno. :tapiro: :tapiro: (Scherzo)


var Result = from valore in Lista
group valore by valore into gruppo
where gruppo.Count()==1
select gruppo.Key;

foreach (int y in Result)
{
Console.WriteLine(y);
}


PS, sto usando Java proprio in questo momento.
e grazie con linq è una cavolata assurda :asd:

EDIT:
tra l'altro non bastava fare:

var processedList = list.Distinct();
foreach (var element in processedList)
{
Console.WriteLine(element);
}

?:mbe:
ah già bisognava eliminarli tutti e due, non solo uno :p

gugoXX
30-06-2008, 16:47
Gia'.
Magari ci sono soluzioni migliori, ma direi che non e' il caso di ottimizzare troppo.

banryu79
30-06-2008, 16:48
E fai bene... ce n'e' bisogno. :tapiro: :tapiro: (Scherzo)

:fuck:


PS, sto usando Java proprio in questo momento.

:yeah:

P.S.: scusate il momento di delirio...

cdimauro
30-06-2008, 19:52
Figurati, tengo alta la bandiera Java! :sofico:
[RASOIO DI OCCAM MODE ON]
Figurati, tengo alta la bandiera! :sofico:
[RASOIO DI OCCAM MODE OFF]

:asd:

DanieleC88
30-06-2008, 19:59
:eh:

^TiGeRShArK^
30-06-2008, 20:40
:eh:

cesare ha bevuto :asd:

cdimauro
01-07-2008, 07:30
Veramente era una battuta sulla "bandiera", e sulle sue "alzate" (specialmente mattutine) che dovrebbero essere ben note ai maschietti. :D

marco.r
01-07-2008, 07:53
e grazie con linq è una cavolata assurda :asd:

In linq e' piu' facile anche perche' fa la cosa piu' intelligente: crea una nuova lista col risultato invece che modificare quella preesistente.
Il ragionamento da fare anche in Java dovrebbe risultare molto piu' semplice (soprattutto se il secondo ciclo lo si fa partire da dopo l'elemento corrente e non dall'inizio)

shinya
01-07-2008, 08:29
In linq e' piu' facile anche perche' fa la cosa piu' intelligente: crea una nuova lista col risultato invece che modificare quella preesistente.
Il ragionamento da fare anche in Java dovrebbe risultare molto piu' semplice (soprattutto se il secondo ciclo lo si fa partire da dopo l'elemento corrente e non dall'inizio)

Si in effetti, io ne avrei creata una nuova in questo caso.

banryu79
01-07-2008, 08:30
Veramente era una battuta sulla "bandiera", e sulle sue "alzate" (specialmente mattutine) che dovrebbero essere ben note ai maschietti. :D
Sì, però l'avevi capita solo te...
In effetti l'associazione di idee per arrivarci era là bella disponibile, d'altronde che cosa avremmo potuto aspettarci da uno che c'ha il chiodo fisso per il Pitone? :asd: :Prrr:

cdimauro
01-07-2008, 13:17
Vabbé, dai, non era difficile, e non serviva il (sacro) pitone per arrivarci. :)

Poi lo sapete che ho una mente contorta e malata, ma quello è un altro discorso... :cool:

banryu79
01-07-2008, 13:20
Bravo, bella parata :D

^TiGeRShArK^
01-07-2008, 13:33
Veramente era una battuta sulla "bandiera", e sulle sue "alzate" (specialmente mattutine) che dovrebbero essere ben note ai maschietti. :D

si, l'avevo capita :asd:
apposta pensavo ti fossi ubriacato :asd:

Tommo
01-07-2008, 19:53
Suppongo che basta non utilizzare for each:



for( int a = 0; a < L.size(); a++)
{
for( int b = 0; b < L.size(); b++)
{
if( L[a] != L[b] && altro)
{
L.remove(a);
L.remove(b);
//quindi indietreggi di a e b di uno, perche' quegli elementi
//non ci sono piu' e la lista si e' accorciata
a--;
b--;
}
}
}



Questa roba scritta senza testare dovrebbe funzionare quasi sicuramente in C++.
Poi non so se Java si occupa per te di rovinare tutto :D

cdimauro
01-07-2008, 20:19
si, l'avevo capita :asd:
apposta pensavo ti fossi ubriacato :asd:
La cosa grave è che non bevo né faccio uso di droghe: almeno una buona scusa l'avrei avuta... :asd:

P.S. Voto per generare una lista d'appoggio o nuova lista con tolti gli elementi via via esclusi. :cool:

jappilas
01-07-2008, 20:43
P.S. Voto per generare una lista d'appoggio o nuova lista con tolti gli elementi via via esclusi. che è interessante che in Diamonds , è stato adottato proprio questo accorgimento (dopo un periodo di "deferred delete" - simil garbage collection ) per evitare le concurrent modifications durante una iterazione nella Grid :) public void runIteration(DroppableIteration iteration)
{
for (Droppable droppable : new DroppableList(droppableList))
{
iteration.executeOn(droppable);
}
}

marco.r
01-07-2008, 23:11
P.S. Voto per generare una lista d'appoggio o nuova lista con tolti gli elementi via via esclusi. :cool:
Generare la lista tra l'altro ha un effetto collaterale interessante: puoi cominciare ad usare il risultato ben prima di finire l'elaborazione. Ora ovviamente nel caso particolare stiamo usando una lista collegata, per cui magari il problema non si pone, pero' in generale se usiamo iteratori non sappiamo quando finiscono... se sono il risultato della lettura di un socket potrebbero non finire "mai".
Dovrebbe venire qualcosa del genere (perdonate se uso Python e non Java, ma non conosco a sufficienza per arrischiarmi a scrivere codice "al volo" :p, spero si capisca ugualmente)

def filterSeen( stream ):
seen = Set()
for x in stream:
if not x in seen:
seen.add(x)
yield x

Probabilmente e' il modo piu' efficiente per farlo (n log(n) invece dell'n^2 iniziale), oltre che uno dei piu' semplici.
Nel caso in questione ho per semplicita' usato l'uguaglianza come metodo di confronto, dover usare una funzione piu' generale con un Set potrebbe essere complicato in Java, o forse no, boh :p.

gugoXX
01-07-2008, 23:36
Non sono d'accordo con il risultato.
Se non sbaglio questo codice restituisce i Distinct.
Invece noi si voleva togliere proprio quelli che sono ripetuti (almeno) 2 volte.
Quindi cadrebbe il discorso dello STREAM. Fino che non hai letto tutto non sai se un elemento comparira' un'altra volta, da non restituire quindi mai, oppure no.

Comunque la versione LINQ e' O(N), penso che anche il Pyton si possa scrivere con questa complessita'.

marco.r
02-07-2008, 00:17
Non sono d'accordo con il risultato.
Se non sbaglio questo codice restituisce i Distinct.
Invece noi si voleva togliere proprio quelli che sono ripetuti (almeno) 2 volte.
Quindi cadrebbe il discorso dello STREAM. Fino che non hai letto tutto non sai se un elemento comparira' un'altra volta, da non restituire quindi mai, oppure no.

Comunque la versione LINQ e' O(N), penso che anche il Pyton si possa scrivere con questa complessita'.
Oibo', hai ragione... dovrei mettere in black list gli ip del forum dopo una certa ora.... fate come se non l'avessi mai scritto... :D

marco.r
02-07-2008, 00:23
Comunque la versione LINQ e' O(N), penso che anche il Pyton si possa scrivere con questa complessita'.

Dovrebbe bastare accumulare in una hash table e poi prendere solo le sequenze di lunghezza 1.

gugoXX
02-07-2008, 00:32
Dovrebbe bastare accumulare in una hash table e poi prendere solo le sequenze di lunghezza 1.

Si', infatti, penso anche io.
Penso sia proprio quello che fa il Linq sotto la coperta.

Per dovere di terminologia, una Hashtable in cui il valore di ogni chiave non e' un singolo elemento, ma e' una lista o altra struttura non scalare (Come questo caso) non si potrebbe chiamare hashtable, ma si potrebbe chiamare solo LookUp, di cui la hastable e' un caso particolare.
Poi ovviamente ci si capisce, tanto piu' che anche ciascuna singola lista puo' essere considerata come entita' singola. Anzi, in OOP e' sicuramente a sua volta un oggetto.
Ma se si vuole fare gli eleganti...

Tipica operazione, la DNS lookup.
Dato un domain name si richiede l'inidirizzo IP.
Ma ad un dominio possono essere associati piu' indirizzi IP, di qui Lookup e non Hash.

^TiGeRShArK^
02-07-2008, 03:46
Dovrebbe bastare accumulare in una hash table e poi prendere solo le sequenze di lunghezza 1.

con l'ordinamento è banale, perchè se scorri la lista al contrario basta fare qualcosa del genere:

for (int i = orderedList.size() - 1; i > 0; i--) {
if (orderedList(i) == orderedList(i - 1)) {
orderedList.remove(i);
}
}

Comunque sei sicuro che la lista sia una buona soluzione nel tuo caso?
Ogni volta che rimuovi un elemento tutti gli elementi successivi vengono shiftati di uno.... :fagiano:
Imho vedrei meglio una HashMap anche se non ho ancora ben capito a cosa ti serve..
In + nella hashmap elimini il problema degli elementi uguali dato che nella stessa chiave ci può stare un solo valore...

:cool:
ovviamente con una hashmap <String, List> :p

cdimauro
02-07-2008, 07:27
In Python dovrebbe venire qualcosa del genere:
def Singoli(Lista):
Gruppi = {}
for Chiave in Lista:
Gruppi[Chiave] = Gruppi.get(Chiave, 0) + 1
return [Chiave for Chiave, Valore in Gruppi.iteritems() if Valore == 1]
P.S. In attesa di Python 3.0 per ridurre il tutto a una sola riga di codice (così mi prendo una randellata da Fran :p).