Newsgroup: it.comp.lang.c++
Titolo: cancellare doppi in una multimap

Ciao a tutti, qual'e' il modo + efficiente per implementare la funzione 
delete_doubles nell'esempio seguente?
Grazie in anticipo
Francesco
#include <map>
typedef std::multimap<int,int> my_multi_map;
//usata nell'esempio per riempire la mappa
void insert_in_map(my_multi_map& map,int k, int vmax)
{
     int v = 0;
     for(int i =0; i<vmax; ++i)
     {
         map.insert(std::make_pair(k,v));
         ++v;
     }
}
//cancella i doppi
//definizione di doppio: stessaK, stessoV
void delete_doubles(my_multi_map& map)
{}
int main()
{
     my_multi_map mm;
     insert_in_map(mm,0,4);
     //map content: (0,0),(0,1),(0,2),(0,3)
     insert_in_map(mm,0,2);
     //map content: (0,0),(0,1),(0,2),(0,3), (0,0),(0,1)
     delete_doubles(mm);
     //expected map content: (0,0),(0,1),(0,2),(0,3)
     return true;
}

int>::operator=(const std::pair<const int, int>&)’ first required here 
non capisco di cosa si lamenti
Ciao


Temo che non ci sia un modo semplice. Io ciclerei su tutte le chiavi e
per ogni chiave cercherei i duplicati. Attenzione che a parita' di
chiave non hai garanzie sull'ordine degli elementi. Questa sembra
funzionare:
void delete_doubles(my_multi_map& map) {
    my_multi_map::iterator i = map.begin();
    int k = i->first;
    std::set<int> founds;
    while ( i != map.end() ) {
        if ( i->first == k ) {
            if ( founds.find(i->second) != founds.end() )
                i = map.erase(i);
            else {
                founds.insert(i->second);
                ++i;
            }
        }
        else {
            founds.clear();
            k = i->first;
        }
    }
}
Probabilmente la cosa migliore e' partire direttamente con un set di
pair, in modo che l'unicita' ti sia garantita all'inserimento.

 pair, in modo che l'unicita' ti sia garantita all'inserimento.
Forse potrebbe andare bene anche un
  map< int , set< int > >
Max

 
nesuno sa perchè si imminchia con pair ?
Ciao

 ha scritto:

Si lamenta del fatto che cerchi di scambiare elementi di un
contenitore associativo.
Ciao,
Nicola


std::unique cmq sembra non apprezzare le pairs:
void delete_doubles(my_multi_map& map)
{
     std::vector< std::pair<int,int> > test(map.begin(), map.end());
     map.clear();
     std::vector< std::pair<int,int> >::iterator it = 
std::unique(test.begin(), test.end());
     map.insert(test.begin(), it);
}
... in map (e pure in vector, prima e dopo la unique) rimane il 
contenuto iniziale (gcc 4.1)!
---
Bye,
  Gabry

 contenuto iniziale (gcc 4.1)!
No, e' che devi ordinare il vector. std::unique() elimina elementi
duplicati *contigui*.
Ciao,
Nicola

 
pensavo non puo dipendere anche dal fatto che sia ordinato? scambiando
gli elementi per l'ordine e quindi si incazza. Se faccio la stessa cosa
su una hashmap mi da errore lo stesso ?
Grazie
CIao

 
mi rispondo da solo, si è lo stesso! ho provato con l'hash_map delle
stlport

 int>use default assignment operator
'unique' vorrebbe usare l'operatore assegnamento per spostare i valori nella
sequenza, ma non č possibile *assegnare* un valore a un pair<const K,V>
perché il 'first' č 'const'.
Max

 chiave non hai garanzie sull'ordine degli elementi. 
Complichiamo le cose:
La tua soluzione funziona per una multimap di tipo <int,int>.
E per una multimap di tipo <int,struct>?
Allego il codice di esempio
Ciao
Francesco
#include <map>
struct evento
{
     int p;
     int k;
};
typedef std::multimap<int,evento> my_multi_map;
//deletes repeated pairs
void delete_doubles(my_multi_map& map)
{
}
int main()
{
     my_multi_map mm;
     struct evento s0; s0.p = 0; s0.k = 0;   //s0 (0,0)
     struct evento s1; s1.p = 1; s1.k = 1;   //s1 (1,1)
     struct evento s2=s1;                    //s2 (1,1)
     mm.insert(std::make_pair(0,s0));        // (0, s0)
     mm.insert(std::make_pair(0,s1));        // (0, s1)
     mm.insert(std::make_pair(1,s0));        // (1, s0)
     mm.insert(std::make_pair(1,s1));        // (1, s1)
     mm.insert(std::make_pair(1,s2));        // (0, s2)
     mm.insert(std::make_pair(0,s2));        // (1, s2)
     delete_doubles(mm);
     //expected map content: (0,s0)
     //                      (0,s1)
     //                      (1,s0)
     //                      (1,s1)
     return true;
}

 funzione delete_doubles nell'esempio seguente?
usare la standard library.  in <algorithms> sono definiti dei metodi
unique() e unique_copy() che mi paiono il cacio sui maccheroni.
-- 
|   Maurizio Loreti -- 
ROT13:ybe...@cq.vasa.vg
   |  (@_
| Un. of Padova, Dept. of Physics, Padova, Italy |  //\
|     
http://www.pd.infn.it/~loreti/mlo.html
     |  V_/_

 E per una multimap di tipo <int,struct>?
il codice di Nicola dovrebbe andare bene (non ho provato) devi 
però definire gli operatori di confronto per la struct.
Ciao
-- 
Andrea Corradi | Debian User | 
www.debian.org
Fingerprint: A41E F6B0 DBDB F04C 4940 E411 30F3 CD62 57B1 8458
gpg --keyserver 
keyserver.linux.it
 --recv-key 57B18458
Please avoid sending me Word or PowerPoint attachments.
http://www.gnu.org/philosophy/no-word-attachments.html

 unique() e unique_copy() che mi paiono il cacio sui maccheroni.
Non tanto. unique() non si puo' usare, perche' modifica la sequenza e
unique_copy() si aspetta che gli elementi equivalenti siano contigui,
mentre la multimap non garantisce alcun ordinamento a parita' di
chiave.
Probabilmente e' la scelta di multimap come contenitore che non e'
adatta al problema.
Ciao,
Nicola

 adatta al problema.
Uso la multimap per rappresentare un flusso midi
class evento
{
public:
	enumerations
 
	costruttore
	distruttore
 
	funzioni di accesso
 
private:
	enum tipo_;
	int length_;
	int key_;
	int channel_;
}
std::multimap<tempo, event>
tempo e' un int.
e puo' succedere (spesso) che allo stesso tempo ci siano 2 o piu'eventi, 
per esempio degli accordi.
Quale potrebbe essere un container piu' adatto?
Grazie
Francesco


Dipende da cosa ci fai nel dettaglio. Ad esempio se l'ordine temporale
e' dato in partenza, ad esempio perche' stai campionando, l'uso di un
contenitore associativo puo' essere inutile e potresti trovarti
addirittura meglio con un vector o con un vector di vector, per
evitare le riallocazioni.
Dal punto di vista diametralmente opposto la tua domanda fa pensare
che sia importante mantenere una relazione d'ordine tra gli eventi
riferiti allo stesso istante ed in questo senso potrebbe risultare
adeguato un set di pair<tempo, event>, con un criterio di ordinamento
definito ad hoc.
Un aspetto importante e' dato dai vincoli prestazionali: puoi fare la
scelta piu' comoda o la cosa piu' importante e' la velocita'? La
risposta in questo caso puo' essere data solo da test pratici.
Ciao,
Nicola

 risposta in questo caso puo' essere data solo da test pratici.
In realta', nello stesso istante potrei avere fino a
16 canali * (127 note + 127 controller)
eventi di tipo diverso e comunque, oltre all'altissima improbabilita' di 
una situazione del genere (un accordo di 127 note su ogni canale ;-) non 
credo sia un problema per il calcolatore.
Potrei davvero fare la scelta piu' comoda!
Molte molte grazie
Francesco