作为 cmets,我收到了很多答案,所以为了后代(以及我自己的理智),我将这些作为实际答案写下来。
元组通过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 的评论:您可以将稀疏索引数组创建为一维元胞数组。这是一个简单粗暴的类模型:
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 只产生二维数组)。另请注意,这些解决方案中的任何一个都可以包装在这样的类中。