MATLAB containers.Map以元组为关键

时间:2017-09-07 18:56:28

标签: matlab dictionary

我想创建一个使用元组(例如containers.Map)的[4,1]对象作为密钥。但是,这不是有效的密钥类型。如何将其转换为有效的密钥类型?

我的最终目标是拥有像稀疏单元格数组的东西,我可以像矩阵一样索引但存储任意对象。

1 个答案:

答案 0 :(得分:2)

我收到很多答案作为评论,所以对于后代(以及我自己的理智),我将这些作为实际答案写出来。

通过sub2ind

标量到标量

如果您尝试模拟具有已知大小的稀疏矩阵的行为,则可以使用sub2ind将任何有效元组转换为唯一的线性索引。

例如,如果您的假设稀疏单元格数组的大小为1000 x 200,那么您可以这样做:

sp_cell = containers.Map('KeyType','double', 'ValueType','any');
key_converter = @(i,j) sub2ind([1000,200], i,j);
sp_cell(key_converter(4,1)) = 'foo';

通过mat2str

串起来的字符串

或者(更一般地说),您可以使用mat2str将元组转换为字符串,但是您将失去sub2ind提供的数组索引边界的检查:

sp_cell = containers.Map('KeyType','char', 'ValueType','any');
key_converter = @(tup) mat2str(tup);
sp_cell(key_converter([4 1])) = 'bar'

元组作为unicode字符串

this answer开始:如果每个索引小于或等于65535,则可以直接将元组转换为字符串。

key_converter = @(tup) char(tup);

散列

this answer开始:您可以将元组散列为字符串。

md = java.security.MessageDigest.getInstance('MD5');
key_converter = @(tup) char(md.digest(tup));

这方面的缺点是你无法将地图密钥转换回元组。

稀疏查找表

来自@ SamRobert的评论:您可以在1-D单元阵列中创建稀疏的索引数组。这是一个快速而又脏的类的模型:

classdef SparseCellArray
    properties (Access=protected)
        lookup
        contents
    end
    methods
        function self = SparseCellArray(m,n)
            % Constructor; takes array dimensions as [#rows, #cols]
            self.lookup = sparse(m,n);
            self.contents = {};
        end
        function B = subsref(self, S)
            % Overload matrix-style indexing
            assert(isscalar(S) && strcmp(S.type,'()'));
            idx = self.lookup(S.subs{1}, S.subs{2});
            assert(idx ~= 0, 'Index not found');
            B = self.contents{idx};
        end
        function newobj = subsasgn(self, S, B)
            % Overload matrix-style indexing 
            assert(isscalar(S) && strcmp(S.type,'()'));
            idx = self.lookup(S.subs{1}, S.subs{2});
            newobj = self;
            if (idx == 0)
                idx = length(self.contents) + 1;
                newobj.lookup(S.subs{1}, S.subs{2}) = idx;
            end
            newobj.contents{idx} = B;
        end
    end
end

用法如下:

sp_cell = SparseCellArray(2000,100);
sp_cell(4,1) = 'foo';

缺点是它只接受二维数组(因为sparse只生成二维数组)。另请注意,这些解决方案中的任何一个都可以包含在这样的类中。