Dictionary / Map with array as key

조회 수: 63 (최근 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 CenterFile Exchange에서 Data Import from MATLAB에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by