Hash-Tabellen in MATLAB

92

Unterstützt MATLAB Hash-Tabellen?


Einige Hintergrundinformationen

Ich arbeite an einem Problem in Matlab, das eine Skalierungsraumdarstellung eines Bildes erfordert. Zu diesem Zweck erstelle ich einen 2-D-Gauß-Filter mit einer Varianz sigma*s^kfür keinen bestimmten Bereich. Anschließend filtere ich das Bild nacheinander. Jetzt möchte ich eine Art Zuordnung kzum gefilterten Bild.

Wenn kimmer eine ganze Zahl wäre, würde ich einfach ein 3D-Array erstellen, so dass:

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

Ist kjedoch nicht unbedingt eine Ganzzahl, daher kann ich dies nicht tun. Ich dachte daran, eine Reihe von ks so zu halten, dass:

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

Was auf den ersten Blick ziemlich gut erscheint, außer dass ich diese Suche möglicherweise einige tausend Mal mit etwa 20 oder 30 Werten von durchführen werde k, und ich befürchte, dass dies die Leistung beeinträchtigen wird.

Ich frage mich, ob es mir nicht besser wäre, dies mit einer Hash-Tabelle zu tun, damit ich eine Suchzeit habe, die O (1) anstelle von O (n) ist.


Jetzt weiß ich, dass ich nicht vorzeitig optimieren sollte, und ich habe dieses Problem möglicherweise überhaupt nicht, aber denken Sie daran, dies ist nur der Hintergrund, und es kann Fälle geben, in denen dies wirklich die beste Lösung ist, unabhängig davon, ob es die ist beste Lösung für mein Problem.

Nathan Fellman
quelle

Antworten:

14

Matlab unterstützt keine Hashtabellen. EDIT Bis r2010a, das heißt; siehe @Amros Antwort.

Um Ihre Suche zu beschleunigen, können Sie das löschenfind und LOGICAL INDEXING verwenden .

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

oder

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

Nach all meinen Erfahrungen mit Matlab hatte ich jedoch noch nie einen Engpass bei der Suche.


Um Ihr spezifisches Problem zu beschleunigen, empfehle ich, entweder inkrementelle Filterung zu verwenden

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

Angenommen, es array_of_kswird in aufsteigender Reihenfolge sortiert, und GaussFilter berechnet die Filtermaskengröße basierend auf der Varianz (und verwendet natürlich 2 1D-Filter), oder Sie können im Fourierraum filtern, was besonders für große Bilder nützlich ist und wenn die Varianzen sind gleichmäßig verteilt (was sie höchstwahrscheinlich leider nicht sind).

Jonas
quelle
120

Erwägen Sie die Verwendung der Kartenklasse von MATLAB: container.Map . Hier ist eine kurze Übersicht:

  • Schaffung:

    >> 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
  • Sieh nach oben:

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

    rainfallMap('Jan') = 0;
  • Hinzufügen:

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

    rainfallMap.remove('Total')
  • Prüfen:

    values = rainfallMap.values;
    keys = rainfallMap.keys;
    sz = rainfallMap.size;
  • Schlüssel prüfen:

    if rainfallMap.isKey('Today')
        ...
    end
Amro
quelle
7
Wow, das wusste ich nicht! +1. Wissen Sie, ob sie viel schneller als die logische Indizierung sind?
Jonas
3
Containers.Map wurde in MATLAB 7.7 (R2008b) hinzugefügt, siehe mathworks.com/access/helpdesk/help/techdoc/rn/brqyzax-1.html . Neu in R2010a ist ein Konstruktor zum Angeben des Schlüsseltyps sowie des Wertetyps. M = container.Map ('KeyType', kType, 'ValueType', vType)
zellus
@ Jonas: Ich habe sie nicht ausgiebig verwendet, es wäre interessant zu sehen, wie sie mit der Verwendung der logischen Indizierung für die Suche vergleichen.
Amro
9
@ zellus, @ amro: Ist es nicht ärgerlich, dass es in Matlab keine Historie der Befehle gibt?
Jonas
4
Nachschlagen: rainfallMap ('Jan'); Zuweisen: rainfallMap ('Jan') = 'zero'; Überprüfen Sie: rainfallMap.values; rainfallMap.keys; rainfallMap.size; Check key: rainfallMap.isKey ('Heute');
Evgeni Sergeev
26

Die neuen Container.Map-Klasse von Matlab R2008b (7.7) ist eine verkleinerte Matlab-Version der Schnittstelle java.util.Map . Es bietet den zusätzlichen Vorteil einer nahtlosen Integration in alle Matlab-Typen ( Java Maps kann beispielsweise keine Matlab-Strukturen verarbeiten ) sowie die Möglichkeit seit Matlab 7.10 (R2010a) , Datentypen anzugeben .

Bei seriösen Matlab-Implementierungen, für die Karten / Wörterbücher mit Schlüsselwerten erforderlich sind, sollten weiterhin die Map-Klassen von Java ( java.util.EnumMap , HashMap , TreeMap , LinkedHashMap oder Hashtable ) verwendet werden, um Zugriff auf ihre größeren Funktionen zu erhalten, wenn nicht sogar die Leistung. Matlab-Versionen vor R2008b haben auf keinen Fall eine echte Alternative und müssen die Java-Klassen verwenden.

Eine mögliche Einschränkung bei der Verwendung von Java-Sammlungen besteht darin, dass sie nicht primitive Matlab-Typen wie Strukturen enthalten können. Um dies zu überwinden, konvertieren Sie entweder die Typen herunter (z. B. mithilfe von struct2cell oder programmgesteuert) oder erstellen Sie ein separates Java-Objekt, das Ihre Informationen enthält und dieses Objekt in der Java-Sammlung speichert.

Möglicherweise möchten Sie auch eine reine, objektorientierte (klassenbasierte) Hashtable-Implementierung von Matlab untersuchen, die im Dateiaustausch verfügbar ist .

Yair Altman
quelle
1
Eine andere Matlab klassenbasierte Implementierung wurde heute veröffentlicht: mathworks.com/matlabcentral/fileexchange/28586
Yair Altman
19

Sie könnten Java dafür verwenden.

In Matlab:

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

Aber Sie müssten ein Profil erstellen, um zu sehen, ob Sie dadurch einen Geschwindigkeitsgewinn erzielen, denke ich ...

Tauran
quelle
12

Es ist ein wenig schwierig, aber ich bin überrascht, dass niemand vorgeschlagen hat, Strukturen zu verwenden. Sie können über den Variablennamen auf jedes Strukturfeld zugreifen, struct.(var)wobei es varsich um eine beliebige Variable handeln kann, die entsprechend aufgelöst wird.

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

var = 'a';

display( dict.(var) ); % prints 1
Mark Elliot
quelle
1
Es würde brechen , wenn Sie eine Zahl als Feldnamen verwenden: dict.('2'): mathworks.com/access/helpdesk/help/techdoc/matlab_prog/...
Amro
Außerdem müssen die Variablen Ganzzahlen sein: dict.(['k',num2str(1)])funktioniert, dict.(['k',num2str(1.1)])schlägt jedoch fehl, und wenn die Werte Ganzzahlen sind, können Sie sie zum direkten Indizieren verwenden. Ansonsten ist es eine schöne Idee.
Jonas
@Amro, @Jonas, faire Punkte, wenn die Schlüssel ganze Zahlen wären, müssten Sie diesen Trick nicht verwenden (ein Array wäre sinnvoller) ... wenn die Schlüssel beliebige Floats sind, ist dies etwas schwieriger, aber ich Ich würde ein Präfix mit einem Buchstaben versehen und das .durch ein ersetzen _.
Mark Elliot
6
Die oben genannten Probleme bei der Verwendung von Strukturen können vermieden werden, indem die Zeichenfolgen vor dem Hinzufügen als Feldnamen dict.(genvarname(['k',num2str(1.1)]))
variiert werden
1

Sie können auch den neuen Typ "Tabelle" nutzen. Sie können verschiedene Datentypen speichern und ganz einfach Statistiken daraus abrufen. Weitere Informationen finden Sie unter http://www.mathworks.com/help/matlab/tables.html .

Lei Zhang
quelle