Tabelle hash in MATLAB


92

MATLAB supporta le tabelle hash?


Qualche sfondo

Sto lavorando a un problema in Matlab che richiede una rappresentazione in scala di un'immagine. Per fare questo creo un filtro gaussiano 2-D con varianza sigma*s^kper un kcerto intervallo., E poi uso ciascuno di essi a turno per filtrare l'immagine. Ora, voglio una sorta di mappatura kdall'immagine filtrata.

Se kfosse sempre un numero intero, creerei semplicemente un array 3D tale che:

arr[k] = <image filtered with k-th guassian>

Tuttavia, knon è necessariamente un numero intero, quindi non posso farlo. Quello che pensavo di fare era mantenere una serie di messaggi ktale che:

arr[find(array_of_ks_ = k)] = <image filtered with k-th guassian>

Il che sembra abbastanza buono a prima vista, tranne per il fatto che eseguirò questa ricerca potenzialmente alcune migliaia di volte con circa 20 o 30 valori di k, e temo che ciò danneggi le prestazioni.

Mi chiedo se non sarei meglio servito a farlo con una tabella hash di qualche tipo in modo da avere un tempo di ricerca che è O (1) invece di O (n).


Ora, so che non dovrei ottimizzare prematuramente e potrei non avere affatto questo problema, ma ricorda, questo è solo lo sfondo e potrebbero esserci casi in cui questa è davvero la soluzione migliore, indipendentemente dal fatto che sia migliore soluzione per il mio problema.

Risposte:


14

Matlab non supporta gli hashtable. EDIT Fino a r2010a, cioè; vedi la risposta di @Amro .

Per velocizzare le ricerche , è possibile eliminare finde utilizzare INDICIZZAZIONE LOGICA .

arr{array_of_ks==k} = <image filtered with k-th Gaussian>

o

arr(:,:,array_of_ks==k) = <image filtered with k-th Gaussian>

Tuttavia, in tutta la mia esperienza con Matlab, non ho mai avuto una ricerca come un collo di bottiglia.


Per velocizzare il tuo problema specifico, suggerisco di utilizzare il filtro incrementale

arr{i} = GaussFilter(arr{i-1},sigma*s^(array_of_ks(i)) - sigma*s^(array_of_ks(i-1)))

supponendo che array_of_kssia ordinato in ordine crescente, e GaussFilter calcola la dimensione della maschera del filtro in base alla varianza (e utilizza, ovviamente, 2 filtri 1D), oppure puoi filtrare in Fourier Space, che è particolarmente utile per immagini grandi e se le varianze sono spaziati in modo uniforme (cosa che molto probabilmente non sono purtroppo).


120

Prendi in considerazione l'utilizzo della map class di MATLAB: containers.Map . Ecco una breve panoramica:

  • Creazione:

    >> keys = {'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', ...
      'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Annual'};
    
    >> values = {327.2, 368.2, 197.6, 178.4, 100.0,  69.9, ...
      32.3,  37.3,  19.0,  37.0,  73.2, 110.9, 1551.0};
    
    >> rainfallMap = containers.Map(keys, values)
    
    rainfallMap = 
      containers.Map handle
      Package: containers
    
      Properties:
            Count: 13
          KeyType: 'char'
        ValueType: 'double'
      Methods, Events, Superclasses
    
  • Consultare:

    x = rainfallMap('Jan');
  • Assegnare:

    rainfallMap('Jan') = 0;
  • Inserisci:

    rainfallMap('Total') = 999;
  • Rimuovere:

    rainfallMap.remove('Total')
  • Ispezionare:

    values = rainfallMap.values;
    keys = rainfallMap.keys;
    sz = rainfallMap.size;
    
  • Chiave di controllo:

    if rainfallMap.isKey('Today')
        ...
    end
    

7
Wow, non lo sapevo! +1. Sai se sono molto più veloci dell'indicizzazione logica?
Jonas

3
Containers.Map è stato aggiunto in MATLAB 7.7 (R2008b), vedere mathworks.com/access/helpdesk/help/techdoc/rn/brqyzax-1.html . Una novità in R2010a è un costruttore per specificare il tipo di chiave e il tipo di valore. M = containers.Map ('KeyType', kType, 'ValueType', vType)
zellus

@ Jonas: non li ho usati ampiamente, sarebbe interessante vedere come si confrontano con l'uso dell'indicizzazione logica per la ricerca ..
Amro

9
@ zellus, @ amro: non è fastidioso il fatto che non ci sia una cronologia dei comandi in Matlab?
Jonas

4
Lookup: RainMap ('Jan'); Assegna: RainMap ('Jan') = 'zero'; Ispezionare: RainMap.values; RainMap.keys; RainMap.size; Chiave di controllo: RainMap.isKey ('Today');
Evgeni Sergeev

26

La nuova classe containers.Map di Matlab R2008b (7.7) è una versione Matlab ridotta dell'interfaccia java.util.Map . Ha l'ulteriore vantaggio di una perfetta integrazione con tutti i tipi di Matlab ( Java Maps non è in grado di gestire le strutture Matlab, ad esempio), nonché la capacità a partire da Matlab 7.10 (R2010a) di specificare i tipi di dati .

Le implementazioni di Matlab serie che richiedono mappe / dizionari di valori-chiave dovrebbero comunque utilizzare le classi Map di Java ( java.util.EnumMap , HashMap , TreeMap , LinkedHashMap o Hashtable ) per ottenere l'accesso alle loro funzionalità più ampie se non alle prestazioni. Le versioni Matlab precedenti alla R2008b non hanno in ogni caso vere alternative e devono utilizzare le classi Java.

Una potenziale limitazione dell'utilizzo delle raccolte Java è la loro incapacità di contenere tipi Matlab non primitivi come gli struct. Per ovviare a questo problema, converti i tipi (ad esempio, utilizzando struct2cell o programmaticamente) o crea un oggetto Java separato che conterrà le tue informazioni e memorizzerà questo oggetto nella Java Collection.

Potresti anche essere interessato a esaminare un'implementazione Hashtable orientata agli oggetti (basata su classi) puro Matlab, disponibile su File Exchange .


1
Un'altra implementazione basata su classi Matlab pubblicata oggi: mathworks.com/matlabcentral/fileexchange/28586
Yair Altman

19

Potresti usare java per questo.

In matlab:

dict = java.util.Hashtable;
dict.put('a', 1);
dict.put('b', 2);
dict.put('c', 3);
dict.get('b')

Ma dovresti fare un po 'di profiling per vedere se ti dà un guadagno di velocità immagino ...


12

È un po 'ingombrante, ma sono sorpreso che nessuno abbia suggerito di usare gli struct. È possibile accedere a qualsiasi campo struct per nome variabile come struct.(var)dove varpuò essere qualsiasi variabile e si risolve in modo appropriato.

dict.a = 1;
dict.b = 2;

var = 'a';

display( dict.(var) ); % prints 1

1
Si interromperà se usi un numero come nome di campo dict.('2'):: mathworks.com/access/helpdesk/help/techdoc/matlab_prog/…
Amro

Inoltre, le variabili devono essere numeri interi: dict.(['k',num2str(1)])funziona, ma dict.(['k',num2str(1.1)])fallisce, e se i valori sono interi, puoi usarli per indicizzare direttamente. Altrimenti è una bella idea.
Jonas

@Amro, @Jonas, punti giusti, se le chiavi fossero numeri interi non avresti bisogno di usare questo trucco (un array avrebbe più senso) ... se le chiavi sono float arbitrarie questo è un po 'più impegnativo, ma io prefisso con una lettera e sostituisci .con un _.
Mark Elliot

6
I problemi di cui sopra con l'utilizzo delle strutture possono essere evitati variabilizzando le stringhe prima di aggiungerle come nomi di campo:dict.(genvarname(['k',num2str(1.1)]))
foglerit

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.