2013-05-23 6 views
8

Posso riformulare la domanda in "Come selezionare il primo elemento in un multiset?" perché sembra che Multiset sia già ordinato in base alle frequenze.Seleziona elemento con occorrenza massima in Multiset

I have a Multiset myList = Multiset.create();

[maa00 mfnt11 malignlft mbold mlt18 mfl x 3, caa00 cfnt11 calignlft cbold clt17 cfl] 

non ho potuto trovare alcun metodo come myList.getIndex (0). Nota, alla fine, ho bisogno del numero di elementi che ha la frequenza massima.

C'è qualche rivestimento per questo? O devo fare quell'iterazione?

Update: sto ottenendo la massima frequenza utilizzando:

myList.count(Multisets.copyHighestCountFirst(myList).asList().get(0))); 

Ma questo è troppo lento. Potete per favore suggerire, che cosa dovrei usare esattamente?

Aggiornamento 1: l'utilizzo del metodo copyHighestCountFirst è troppo lento. In un'istanza del ciclo, ci vogliono 80 + millisecondi contro la media di 40 millisecondi senza. In loop grandi, dovrei preferire l'iterazione semplice?

Aggiornamento 2: ottenuto che funziona con:

myList.count(myList.entrySet().iterator().next().getElement()) 

Senza quasi a zero impatto sulle prestazioni. Mi chiedo ancora se ci sia un modo migliore per farlo.

Nota a margine: In Python ho fatto lo stesso con:

j = defaultdict(int) 
for k in clList: 
    j[k] +=1 
result1 = max(j.iteritems(), key=lambda x:x[1]) //count of frequency of item with max count 

risposta

14

C'è stato un sacco di alternative gettati in giro tra la domanda e l'altra risposta postato, ma molti di loro sembrano dipendere l'idea che .get(0) o .iterator().next() sta per ottenere l'elemento più frequente. Non lo farà!

Le tue uniche due scelte decenti sono Multisets.copyHighestCountFirst(bag).elementSet().iterator().next(), che è uno spreco come dici tu, o fai un ciclo attraverso lo entrySet manualmente e controlla ciascuna per vedere se è la più frequente finora.

È necessario presentare una richiesta di funzione Guava per estrarre l'elemento più frequente. Non posso promettere cosa accadrà, ma vale la pena richiederlo.

2

A causa del le modifiche e fraseggio non è chiaro ciò che si desidera. Inoltre, usando myList come nome di variabile che è un multiset non è descrittivo - Userò bag come nome di variabile per il multiset (è dopotutto borsa).

  1. "sembra Multiset è già ordinata secondo frequenze" - è vero o non è ordinata secondo le frequenze?

    ImmutableMultiset<String> bag = ImmutableMultiset.of(
        "c0ffee", "abba", "mfl", "mfl", "mfl", "c0ffee"); 
    

    è [c0ffee x 2, abba, mfl x 3] perché utilizza ordine di inserimento, in modo dalla vostra collezione può essere ordinato correttamente per caso (non so se si tratta di un caso qui). Se non siete sicuri su ordinazione, basta usare

    ImmutableMultiset<String> sortedBag = Multisets.copyHighestCountFirst(bag) 
    

    che dà [mfl x 3, c0ffee x 2, abba]. Poiché Multisets.copyHighestCountFirst restituisce il multiset immutabile, non è necessario utilizzarlo in loop presupponendo che il multiset non cambi. Se hai appena fatto uno stupido microbenchmark e hai visto che usare Multisets.copyHighestCountFirst è due volte più lento, ovvero 80 ms contro 40 ms, dimenticalo perché premature optimization is the root of all evil. Presumo che abbiamo ordinato correttamente sortedBag a questo punto.

  2. Da quello che vedo che vuoi conteggio di più elemento comune in sacchetto che è semplicemente:

    int count = sortedBag.entrySet().iterator().next().getCount(); 
    

    o se il multiset è ImmutableMultiset:

    int count = sortedBag.entrySet().asList().get(0).getCount(); 
    

    Nota che sortedBag.entrySet() è un raccolta di Multiset.Entry che ha sia l'elemento che il conteggio, quindi scegli quello che vuoi.

  3. Avere ImmutableMultiset consente di utilizzare è ImmutableList vista su cui è possibile chiamare get(0) per recuperare elemento:

    sortedBag.asList().get(0) 
    

    che vi dà unico elemento (qui: una stringa), senza contare, quindi se il vostro piano è per recuperare solo elementi è possibile utilizzare asList() invece di giocare con iteratore.

+0

I ho capito adesso. Grazie. – akshayb

3

Una soluzione alternativa che non richiederebbe un ciclo esplicito - ma sarebbe eseguito in tempo lineare nel numero di elementi distinti, che la maggior parte di queste soluzioni non possono - sarebbe

Ordering.natural().onResultOf(new Function<Multiset.Entry<Foo>, Integer>() { 
    public Integer apply(Multiset.Entry<Foo> entry) { 
    return entry.getCount(); 
    } 
}.max(multiset.entrySet()).getElement();