如何在MATLAB中使用哈希表(字典)?

35

我需要通过字符串索引访问数据,例如 table('one') %返回 1。MATLAB 中是否有这样的数据结构?它是如何实现的?


1
(也是http://www.mathworks.com/matlabcentral/answers/21130-dictionaries-of-hashtables-in-matlab的交叉复制) - Franck Dernoncourt
3个回答

55
在最近的MATLAB版本中,有一个叫做`containers.Map`的数据结构。详见MATLAB Map containers以了解更多信息。这个数据结构消除了使用STRUCTs时的一些限制。例如,
c = containers.Map
c('foo') = 1
c(' not a var name ') = 2
keys(c)
values(c)

2
来自未来的注释:自MATLAB R2022b起,dictionary已被推荐使用,而不是containers.Map。请参阅此重复问题以了解如何使用dictionary - undefined

17

结构体可以被用作一种哈希表的形式:

>> foo.('one')=1

foo = 

    one: 1

>> foo.('two')=2;
>> x = 'two';
>> foo.(x)

ans =

     2

要查询一个结构体是否包含特定的字段(键),使用isfield

>> isfield(foo,'two')

ans =

     1

这种方案的缺点是,只有那些同时也是有效 Matlab 变量名的字符串才能用作键。例如:

>> foo.('_bar')=99;
??? Invalid field name: '_bar'.
为了避免这种限制,使用Oli链接的问题中提供的解决方案之一。

这种方法的另一个缺点是键的名称必须少于namelengthmax(63)个字符。 - rhombidodecahedron

0

仅作为对之前答案的补充(无法评论其他好的答案):像这样进行结构查找:

s={};
s.abc = 1;   %insert a value in the struct, abc is your lookup hash
out = s.abc; % read it back

使用结构体读取值的实际速度比使用容器快约10倍。如果有兴趣,以下是完整的测试代码。

function s=test_struct_lookup_hash_speed
%% test how a struct lookup speed works vs container, interesting

    s = {};  % hash table
    v = {};  % reverselookup table for testing

    nHashes = 1E4;  % vary this to see if read speed varies by size (NOT REALLY)
    nReads  = 1E6;

    fprintf('Generating hash struct of %i entries\n', nHashes);
    tic
    for i = 1:nHashes
        hashStr = md5fieldname(randi(1E8));
        s.(hashStr) = i;
        v{end+1} = hashStr;  %reverselookup
    end
    toc

    fprintf('Actual HashTable length (due to non unique hashes?): %i, and length of reverse table: %i\n',length(fieldnames(s)), length(v) );

    fprintf('Reading %i times from a random selection from the %i hashes\n', nReads, nHashes);
    vSubset = [ v(randi(nHashes,1,3))  ];

    for i = 1:length(vSubset)
       hashStr = vSubset{i};

       % measure read speed only
       tic
       for j = 1:nReads
         val = s.(hashStr);
       end
       toc

    end


    %% test CONTAINERS
    fprintf('Testing Containers\n');
    c = containers.Map;

    fprintf('Generating hash struct of %i entries\n', nHashes);
    tic
    for i = 1:nHashes
        hashStr = md5fieldname(randi(1E8));
        c(hashStr) = i;
        v{end+1} = hashStr;  %reverselookup
    end
    toc

   fprintf('Reading %i times from a random selection from the %i hashes\n', nReads, nHashes);
   vSubset = [ v(randi(nHashes,1,3))  ];

    for i = 1:length(vSubset)
       hashStr = vSubset{i};

       % measure read speed only
       tic
       for j = 1:nReads
         val = c(hashStr);
       end
       toc

    end    



    %% Get a valid fieldname (has to start with letter)   
    function h=md5fieldname(inp)
    h = ['m' hash(inp,'md5')];
    end


end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接