Tables de hachage dans MATLAB

92

MATLAB prend-il en charge les tables de hachage?


Un peu de contexte

Je travaille sur un problème dans Matlab qui nécessite une représentation échelle-espace d'une image. Pour ce faire , créer un filtre gaussien 2-D avec une variance sigma*s^kpour une kcertaine plage., Puis - je utiliser chacun à son tour pour filtrer l'image. Maintenant, je veux une sorte de mappage de kl'image filtrée.

Si kc'était toujours un entier, je créerais simplement un tableau 3D tel que:

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

Cependant, ce kn'est pas nécessairement un entier, donc je ne peux pas faire cela. Ce que j'ai pensé à faire était de garder un tableau de ks tels que:

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

Ce qui semble plutôt bon à première vue, sauf que je vais faire cette recherche potentiellement plusieurs milliers de fois avec environ 20 ou 30 valeurs de k, et je crains que cela nuise aux performances.

Je me demande si je ne serais pas mieux servi de faire cela avec une table de hachage de sorte que j'aurais un temps de recherche qui est O (1) au lieu de O (n).


Maintenant, je sais que je ne devrais pas optimiser prématurément, et je n'ai peut-être pas du tout ce problème, mais rappelez-vous, ce n'est que l'arrière-plan, et il peut y avoir des cas où c'est vraiment la meilleure solution, que ce soit ou non le meilleure solution pour mon problème.

Nathan Fellman
la source

Réponses:

14

Matlab ne prend pas en charge les hashtables. EDIT Jusqu'à r2010a, c'est-à-dire; voir la réponse de @Amro .

Pour accélérer vos recherches, vous pouvez supprimer findet utiliser LOGICAL INDEXING .

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

ou

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

Cependant, dans toute mon expérience avec Matlab, je n'ai jamais vu de recherche être un goulot d'étranglement.


Pour accélérer votre problème spécifique, je suggère d'utiliser le filtrage incrémentiel

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

en supposant array_of_ksest trié par ordre croissant, et GaussFilter calcule la taille du masque de filtre en fonction de la variance (et utilise, bien sûr, 2 filtres 1D), ou vous pouvez filtrer dans l'espace de Fourier, ce qui est particulièrement utile pour les grandes images et si les variances sont espacés uniformément (ce qu'ils ne sont probablement pas malheureusement).

Jonas
la source
120

Envisagez d'utiliser la classe de carte de MATLAB: containers.Map . Voici un bref aperçu:

  • Création:

    >> 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
    
  • Chercher:

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

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

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

    rainfallMap.remove('Total')
  • Inspecter:

    values = rainfallMap.values;
    keys = rainfallMap.keys;
    sz = rainfallMap.size;
    
  • Clé de vérification:

    if rainfallMap.isKey('Today')
        ...
    end
    
Amro
la source
7
Wow, je ne savais pas ça! +1. Savez-vous s'ils sont beaucoup plus rapides que l'indexation logique?
Jonas
3
Containers.Map a été ajouté dans MATLAB 7.7 (R2008b) voir mathworks.com/access/helpdesk/help/techdoc/rn/brqyzax-1.html . Nouveau dans R2010a est un constructeur pour spécifier le type de clé ainsi que le type de valeur. M = containers.Map ('KeyType', kType, 'ValueType', vType)
zellus
@Jonas: Je ne les ai pas beaucoup utilisés, il serait intéressant de voir comment ils se comparent à l'utilisation de l'indexation logique pour la recherche ..
Amro
9
@ zellus, @ amro: N'est-il pas ennuyeux qu'il n'y ait pas d'historique des commandes dans Matlab?
Jonas
4
Recherche: rainMap ('Jan'); Assign: rainMap ('Jan') = 'zéro'; Inspecter: précipitationsMap.values; rainMap.keys; rainMap.size; Clé de contrôle: rainMap.isKey ('Aujourd'hui');
Evgeni Sergeev
26

La nouvelle classe containers.Map de Matlab R2008b (7.7) est une version réduite de Matlab de l' interface java.util.Map . Il a l'avantage supplémentaire d'une intégration transparente avec tous les types Matlab ( Java Maps ne peut pas gérer les structures Matlab par exemple) ainsi que la capacité depuis Matlab 7.10 (R2010a) de spécifier des types de données .

Les implémentations sérieuses de Matlab nécessitant des mappages / dictionnaires clé-valeur doivent toujours utiliser les classes Map de Java ( java.util.EnumMap , HashMap , TreeMap , LinkedHashMap ou Hashtable ) pour accéder à leurs fonctionnalités plus larges si ce n'est les performances. Les versions de Matlab antérieures à R2008b n'ont en aucun cas d'alternative réelle et doivent utiliser les classes Java.

Une limitation potentielle de l'utilisation des collections Java est leur incapacité à contenir des types Matlab non primitifs tels que les structs. Pour surmonter cela, convertissez les types à la baisse (par exemple, en utilisant struct2cell ou par programme), ou créez un objet Java distinct qui contiendra vos informations et stockera cet objet dans la collection Java.

Vous pouvez également être intéressé par une implémentation de Hashtable orientée objet (basée sur les classes) pure Matlab, qui est disponible sur File Exchange .

Yair Altman
la source
1
Une autre implémentation basée sur les classes Matlab publiée aujourd'hui: mathworks.com/matlabcentral/fileexchange/28586
Yair Altman
19

Vous pouvez utiliser java pour cela.

Dans matlab:

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

Mais il faudrait faire un profilage pour voir si cela vous donne un gain de vitesse je suppose ...

tauran
la source
12

C'est un peu cluge, mais je suis surpris que personne n'ait suggéré d'utiliser des structures. Vous pouvez accéder à n'importe quel champ struct par nom de variable comme struct.(var)varpeut être n'importe quelle variable et résoudra de manière appropriée.

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

var = 'a';

display( dict.(var) ); % prints 1
Mark Elliot
la source
1
Cela se briserait si vous utilisiez un nombre comme nom de champdict.('2') :: mathworks.com/access/helpdesk/help/techdoc/matlab_prog/…
Amro
En outre, les variables doivent être des entiers: dict.(['k',num2str(1)])fonctionne, mais dict.(['k',num2str(1.1)])échoue, et si les valeurs sont des entiers, vous pouvez les utiliser pour indexer directement. C'est une bonne idée autrement.
Jonas
@Amro, @Jonas, justes points, si les clés étaient des entiers, vous n'auriez pas besoin d'utiliser cette astuce (un tableau aurait plus de sens) ... si les clés sont des flottants arbitraires, c'est un peu plus difficile, mais je 'd préfixe par une lettre et remplacez le .par un _.
Mark Elliot
6
Les problèmes ci-dessus liés à l'utilisation des structures peuvent être évités en variabilisant les chaînes avant d'ajouter comme noms de champ:dict.(genvarname(['k',num2str(1.1)]))
foglerit
1

Vous pouvez également profiter du nouveau type "Table". Vous pouvez stocker différents types de données et en tirer des statistiques très facilement. Voir http://www.mathworks.com/help/matlab/tables.html pour plus d'informations.

Lei Zhang
la source