2012-10-09 13 views
5

Ho bisogno di una funzionalità simile all'hashmap in Matlab, dove l'hashmap mappa i vettori ad altri vettori e il numero di vettori (che vanno a centinaia di migliaia) non è noto in anticipo.Coltivare una Hashmap di vettori in Matlab

Ho provato Matlab's integrato Containers.Map, ma che non accetta i vettori come chiavi. Poi ho provato java.util.HashMap:

>> map = java.util.HashMap; 
>> map.put(1:3,zeros(2,1)); 
>> map.get(1:3) 

ans = 

[] 

Così, per qualche ragione che non sembra funzionare, anche se la HashMap Java dovrebbe essere in grado di mappare gli array di array.

L'altra opzione sarebbe quella di mantenere due matrici separate, una per le chiavi e una per i valori, e farle crescere in modo incrementale. Ma non voglio davvero farlo a causa del dolore in Matlab di crescere le cose in modo incrementale (anche con incrementi di dimensioni blocco ecc., Ad esempio here).

Domande: 1. Perché Java HashMap non funziona qui? 2. Altri approcci?

Grazie.

+2

check out http://stackoverflow.com/questions/1352553/how-can-i-use-matlab-arrays-as-keys-to-the-hashmap-java-objects – Rasman

+1

Qual è l'intervallo di valori nel i principali vettori? Se sono sotto i 2^16, puoi semplicemente convertirli in 'char' e usare le stringhe divertenti risultanti come chiavi. –

+0

Grazie a tutti per le vostre risposte. I vettori chiave sono in effetti sotto 2^16, quindi ho confrontato usando contenitori.Mappa con chiavi di caratteri e HashMap di java con tasti simili al post Rasman collegato a: ok è troppo codice per postare qui, quindi lo posterò come risposta. – Matt

risposta

4

Ecco un kludge che fa quello che vuoi. . .

map = java.util.HashMap;  
key = java.util.Vector; 

matKey = 1:3; 
for nn=1:numel(matKey) 
    key.add(matKey(nn)); 
end 

map.put(key,zeros(2,1)); 
map.get(key) 

.. è comunque un punto di partenza.

+1

Questo potrebbe funzionare, ed essere meglio di un "kludge", ma bisogna stare attenti - è un po 'ingannare riutilizzando l'istanza dell'oggetto Java in 'key', quando penso che OP voglia essere in grado di estrarre le voci da valore. Il codice OP non funziona perché Matlab '1: 3' viene convertito in un doppio array primitivo Java, che ha semantica di uguaglianza per identità. Il tuo primo esempio funzionerà se ti ritroverai con un vettore di doppi, che avrà semantica di uguaglianza per valore. Non sono sicuro di come andrà la conversione; potrebbe essere necessario forzarlo facendo 'key.add (java.lang.Double (matKey (nn)));'. –

+1

Il secondo esempio probabilmente non funzionerà - 'key.add (1: 3)' finisce con un vettore lungo un singolo di double [], che termina con l'uguaglianza per identità. Non penso che sarai in grado di estrarre il valore usando un '1: 3' diverso; avresti bisogno dell'oggetto originale 'key'. Per esempio. se fai 'key2 = java.util.Vector; key2.add (1: 3); map.get (key2) ', recupera il valore? Perché penso che sia ciò di cui OP avrà bisogno per farlo funzionare. –

+0

@AndrewJanke eri corretto. Dopo il test, Kludge 2 non ha funzionato. Rimosso – learnvst

1

Ho confrontato i contenitori.Mappa con i tasti di scelta rapida (grazie a Andrew Janke) a java.util.HashMap con un oggetto wrapper come chiave (come in this post, anche grazie a Andrew Janke, e grazie a Rasman per indicarlo) :

numvec = 10^5; 
S = round(rand(numvec,10)*40); 

matmap = containers.Map(); 
%pick a random vector 
idx = ceil(rand()*numvec); 
s1 = S(idx,:); 

%put it in the map 
matmap(char(s1)) = zeros(1,4); 
for i=1:5*10^5 

    if i==10^3 tic; end %allow some time for getting up to speed before timing 

    %pick a random vector and put it in the map 
    idx = ceil(rand()*numvec); 
    s2 = S(idx,:); 
    matmap(char(s2)) = zeros(1,4); 

    %retrieve value of previous vector 
    v = matmap(char(s1)); 

    %modify it randomly and put it back 
    v(ceil(rand()*4)) = rand(); 
    matmap(char(s1)) = v; 

    s1 = s2; 
end 
toc 

javaaddpath('/Test/bin'); 
import test.ArrayKey; 
javmap = java.util.HashMap; 

idx = ceil(rand()*numvec); 
s1 = S(idx,:); 

%also convert value to ArrayKey so we can retrieve it by ref -- saves a put 
%operation 
javmap.put(ArrayKey(s1), ArrayKey(zeros(1,4))); 
for i=1:5*10^5 

    if i==10^3 tic; end 

    idx = ceil(rand()*numvec); 
    s2 = S(idx,:); 
    javmap.put(ArrayKey(s2), ArrayKey(zeros(1,4))); 
    v = javmap.get(ArrayKey(s1)); 
    v.x(ceil(rand()*4)) = rand(); 
    s1 = s2; 
end 
toc 

Risultato:

>> testmaps 
Elapsed time is 58.600282 seconds. 
Elapsed time is 97.617556 seconds. 

containers.Map è il vincitore.


Modifica: Ho eseguito nuovamente il test per numvec = 10^6 e tutto il resto lo stesso. containers.Map approccio eseguito in 59 secondi. L'approccio di HashMap non è stato completato dopo 5 minuti e ha impedito a Matlab di non rispondere.


Edit2: Ho anche provato pre-assegnazione due matrici distinte trovare le chiavi utilizzando ismember. Le prestazioni erano peggiori di HashMap.

+0

Fresco. Ha senso che containers.Map sovraperforma: c'è un sovraccarico per ogni chiamata Java da codice M, e la conversione della chiave utilizza più chiamate, aumentando con la lunghezza della chiave. –

0

Recentemente ho dovuto affrontare un problema simile, non con i vettori ma con gli array.

Matlab ha una funzione mat2str che converte una matrice in una stringa. Se non hai bisogno che i vettori crescano dinamicamente in HashMap, puoi rappresentare il vettore come una stringa e usarlo come chiave/valore. In alcune situazioni questo probabilmente non è molto utile, ma è una soluzione rapida e sporca se le cose sono statiche.

Problemi correlati