将地图matlab转换为字符串键

时间:2015-10-03 03:34:05

标签: arrays matlab dictionary matrix

我的地图定义为:

diagonal = eye(4);
v = {diagonal(1,:), diagonal(2,:), diagonal(3,:), diagonal(4,:)}
k = {1, 3, 7, 8}
class_labels = containers.Map(k, v)

现在我需要一个反向映射,但Matlab不允许键成为数组,因此我需要将每个数组转换为字符串。

所以我的class_labels地图看起来像:

1 => [0 0 0 1]
3 => [0 0 1 0]
7 => [0 1 0 0]
8 => [1 0 0 0]

我需要类似的东西:

0001  => 1
0010  => 3
0100  => 7
1000  => 8

3 个答案:

答案 0 :(得分:1)

您可以使用与keys类关联的valuescontainers.Map方法提取键和值,然后通过将所有位连接在一起对字符串应用字符串转换....然后简单地构建另一个containers.Map。你要做的是使用cellfun迭代值单元格数组的每个单元格元素并应用一个函数,使其将数组中的数字序列转换为连接字符串。

我们暂时假设您无法访问您已定义的键和值,并且我们只能访问containers.Map本身。您想要反转字典,所以:

%// Your code
diagonal = eye(4);
v = {diagonal(1,:), diagonal(2,:), diagonal(3,:), diagonal(4,:)};
k = {1, 3, 7, 8};
class_labels = containers.Map(k, v);

%// New - Get the keys and labels
kr = keys(class_labels);
vr = values(class_labels);

%// Concatenate all of the bits of the values into a string
vr = cellfun(@(x) char(48+x), vr, 'uni', 0);

%// Create new dictionary
new_labels = containers.Map(vr, kr);

这一行可能是最令人困惑的:vr = cellfun(@(x) char(48+x), vr, 'uni', 0);cellfun遍历单元格数组中的所有单元格,并将函数应用于每个单元格。此函数是cellfun的第一个输入。我声明了一个匿名函数,它接收单元格数组中单元格的内容...所以这将是值数组,然后为每个数字添加48。这为我们提供了一个48/49而不是0/1的数组。完成此操作后,我们将此数组转换为char,以便将数字表示为ASCII或字符串等效项。 0/1的ASCII代码为48/49。通过在此已修改的数组上使用char,生成的是一个将所有这些字符连接在一起的字符串。第二个输入是我们正在处理的单元格数组,第三个和第四个参数告诉您cellfun的输出不是数字向量,而是另一个值的单元格数组。 'uni''UniformOutput'的缩写,并且设置为0/false,因为此函数的输出不是数字向量,而是向量的单元格数组。每个单元格都是通过将数值数组中的所有数字连接在一起而创建的字符串。

如果我们显示键和值,我们得到:

>> keys(new_labels)

ans = 

    '0001'    '0010'    '0100'    '1000'

>> values(new_labels)

ans = 

    [8]    [7]    [3]    [1]

您可以看到每个字符串键映射到正确的反向值。

答案 1 :(得分:0)

问题是将数组映射到字符串或双精度,并且可能 再次回来。根据您提供的限制,您可以使用find “编码”向量;单行中无法实现解码(I 不要想),但是像

function idx2vec(i,n)
% I - index to set to 1
% N - length of vector
  v = zeros([1,n]);
  v(i) = 1;
end

您可以使用此技术获取单个参数key->数组 转换器:

function f= fidx2vec(n)
  function v=idx2vec(i)
    v = zeros([1,n]);
    v(i) = 1;
  end
  f = @idx2vec;
end

对于常规数组,您可以使用mat2str(数组到键)和eval (而不是数组的关键)。

为了便于阅读,我在vec2idx中找到了find:

function i=vec2idx(v)
  i = find(v);
end

并将其添加到您的代码中:

diagonal = eye(4);
v = {diagonal(1,:), diagonal(2,:), diagonal(3,:), diagonal(4,:)};
k = {1, 3, 7, 8};
class_labels = containers.Map(k, v);

rk = cellfun(@vec2idx, v, 'uniformoutput', false);

reverse_map = containers.Map(rk, k);

for iv = 1:length(v)
  fprintf('%s -> %g\n',mat2str(v{iv}),reverse_map(vec2idx(v{iv})));
end

生产:

[1 0 0 0] -> 1
[0 1 0 0] -> 3
[0 0 1 0] -> 7
[0 0 0 1] -> 8

最后评论:此解决方案将您的数组映射到正数 整数。 Matlab有一个非常好的容器映射正面 整数加倍,称为数组!如果你的密钥是密集的(即全部 或者大多数将使用1:n的值),我只是使用数组 一个容器。地图。您可以使用nan标记不存在 条目。如果您的密钥稀疏,那么您的数组就是长度 (比方说)1000,但只使用了50种可能性,containers.Map是一个 合理的选择。

答案 2 :(得分:0)

可以使用logical indexing

完成反向地图
 allValues = [1 3 7 8];
 value = allValues(logical(key));

例如,

 >> allValues = [1 3 7 8];
 >> key = [0; 0; 1; 0];
 >> value = allValues(logical(key))
 value =
      7

如果密钥恰好包含多个密钥,则相应的值将作为向量

返回
 >> key = [1; 0; 1; 0];
 >> value = allValues(logical(key))
 value =
      1     7