Dictionary / Map with array as key

64 ビュー (過去 30 日間)
Verena Heußer
Verena Heußer 2020 年 6 月 23 日
編集済み: Verena Heußer 2020 年 7 月 2 日
Hi there,
I'm looking for a way to initialize a map with an array as Key.
I am thinking of something like
map = containers.Map;
state = {1,2};
map(state) = 0;
However, the last line fails with
Error using containers.Map/subsasgn
Specified key type does not match the type expected for this container.
Is there any way I can initialize a Map with an array (not converted to char) as keys?
Or is there any other appropriate data structure for doing this?
Looking forward to your ideas;)
  2 件のコメント
Walter Roberson
Walter Roberson 2020 年 6 月 23 日
The array is to be a single key, right?
Verena Heußer
Verena Heußer 2020 年 6 月 23 日
Yes, I want the key to be an array.

サインインしてコメントする。

回答 (3 件)

Mehmed Saad
Mehmed Saad 2020 年 6 月 23 日
編集済み: Mehmed Saad 2020 年 6 月 27 日
EDIT: First Answer is replaced
I donot understand why you dont want to go on characters. see the code below
M = containers.Map('KeyType','char','ValueType','double');
%% Single Key
key1 = [1.8 2.0 0.005];
valueSet = 327.2;
%% array key encoder
keySet = key_enc(key1);
M = containers.Map(keySet,valueSet);
%% array key decoder
key1_dbl = key_dec(M.keys);
assert(isequal(key1_dbl,key1));
where key_enc is double array to character converter. It basically converts double precision to hexadecimal (so that we dont lose any data due to rounding off)
Similarly key_dec is character to array double converter in order to retreive the key

For 2D Array

M = containers.Map('KeyType','char','ValueType','double');
%% More than 1
key1 = [1.8 2.0 0.005;4 5 6];
valueSet = [327.2 550];
%% array key encoder
keySet = key_enc(key1)
M = containers.Map(keySet,valueSet);
%% array key decoder
key1_dbl = key_dec(M.keys);
assert(isequal(key1_dbl,key1));
Point to remember
  1. a row is a complete key (i.e. a single row vector is considered as 1 key)
  2. key must be double precision (or any other 64 bit type)
  3. if you provide a 2D matrix, the number of rows represent number of keys
  4. key_inc can take both 1D and 2D input, it will return scalar output for 1D row vector. It's output type is cell array of character vectors
  5. key_dec take cell array of character vector as input and will return the double key in that format

Functions

Key Encoder
function key1_char = key_enc(key1)
[m,n] = size(key1);
key1_char=repmat({char(ones(1,16*n))},m,1);
tmp = num2hex(key1);
for ii=1:m
key1_char{ii,:} = reshape((tmp(ii:m:end,:).'),1,16*n);
end
end
Key Decoder
function key1_dbl = key_dec(key1_char)
m = numel(key1_char);
n = numel(key1_char{1});
key1_dbl = zeros(m,n/16);
for ii=1:m
key1_dbl(ii,:) = transpose(hex2num(transpose(reshape(key1_char{ii},16,n/16))));
end
end

Edit:

it is not necessary that assert works everytime because map gives sorted key out
For example
rng(2017)
key1 = randn(2,10);
valueSet =[1 2];
%% array key encoder
keySet = key_enc(key1)
keySet =
2×1 cell array
{'c00151bd6e3dafe9bfcefd29436d4...7b0bfe72b879a67bbee'}
{'3ff0c59e4de6586abff94c4bcb1ceb...ba03fd58526d0d66e84'}
Now see that they are not sorted in ascending order while
M = containers.Map(keySet,valueSet);
M.keys
ans =
1×2 cell array
{'3ff0c59e4de6586abff94c4bcb1ceb433fd72f384820035ebff29c1…'} {'c00151bd6e3dafe9bfcefd29436d4de93fe6733364db1b1fbfe17d1…'}
so if now you check them error will occur (assertion failed)
  5 件のコメント
Walter Roberson
Walter Roberson 2020 年 6 月 26 日
No. Keys can be numeric scalars or character vectors or string() scalars, and cannot be cells and cannot be numeric vectors or non-scalar string objects.
Mehmed Saad
Mehmed Saad 2020 年 6 月 26 日
see the updated answer for double array

サインインしてコメントする。


Walter Roberson
Walter Roberson 2020 年 6 月 26 日
It isn't nice but ...
A container.Map can be a value. So you can create a top level container.Map that has a key that is 1.8, and the associated value is a second container.Map . The second container you would have a key that is 2.0 and associated value is a third container.Map . That third container.Map would have a key 0.005 and value would be whatever you were trying to associate as a value for key1 .
I would not expect this to be efficient. For efficiency, you would probably be better of doing something like an MD5 of key1 and use that as the key. Or see https://www.mathworks.com/matlabcentral/answers/534528-how-to-save-serialize-matlab-variables-to-a-byte-string#answer_439768 with the idea being that you would apply that to key1 and use the result as the key -- the advantage there would be that you would be able to look at the key list and deserialize the key list entries to find out what the resulting numeric keys were.

Verena Heußer
Verena Heußer 2020 年 7 月 2 日
編集済み: Verena Heußer 2020 年 7 月 2 日
Dear all,
thanks for helping me out :)
I just wanted to share the solution I've come up with (don't know if it's the most efficient / elegant, but it totally serves my purposes).
So, I wanted to have arrays (1xn vectors) as keys, while the values are supposed to be real values.
I've decided to use the java.util.hashtable:
map = java.util.Hashtable;
state = [1, 2];
map.put(num2str(state), 0);
map.get(num2str(state))
>> ans =
0

カテゴリ

Help Center および File ExchangeData Import from MATLAB についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by