Phibins
Phibins

Reputation: 121

How to create a Map (Hashtable) that concatenates values to vectors if same key? (example inside)

I am trying to create a hash table that concatenates a value to a vector based on a key (see example).

So there is a Map Class in matlab that behaves like this (you can copy-paste this into matlab):

% I create my first map
keySet =   {'333', '145', '6', '34'}; 
valueSet1 = [327.2, 368.2, 197.6, 178.4]; 
mapObj = containers.Map(keySet,valueSet1)

% Create second map with one or more shared keys (see '333' is a repeated key)
keySet   = {'333','15','765'}; 
valueSet = [ 69.9, 32.3, 37.3]; 
newMap = containers.Map(keySet,valueSet);

% Concatanate these maps
mapObj = [mapObj; newMap];

% The results look like this:
[keys(mapObj)',values(mapObj)'] 

%     [  6]    [197.6000]
%     [ 15]    [ 32.3000]
%     [ 34]    [178.4000]
%     [145]    [368.2000]
%     [333]    [69.9000]
%     [765]    [ 37.3000]

You see how the value 327.2 for the key '333' was replaced by 69.9?

What I am trying to do is to concatenate any values with a shared key so that the output look like:

[keys(mapObj)',values(mapObj)'] 

%     [  6]    [197.6000]
%     [ 15]    [ 32.3000]
%     [ 34]    [178.4000]
%     [145]    [368.2000]
%     [333]    [327.2000, 69.9000]     <<<<<< This is what i'm trying to do
%     [765]    [ 37.3000]

But I can't figure out how to do this efficiently.

Upvotes: 2

Views: 140

Answers (1)

sco1
sco1

Reputation: 12214

The trivial solution is to make your own map joining helper function that checks for shared keys between the two maps and concatenates them if necessary.

For example:

function outMap = mapjoin(map1, map2)
sharedkeys = intersect(map1.keys, map2.keys);

outMap = [map1; map2];
if ~isempty(sharedkeys)
    for ii = 1:numel(sharedkeys)
        key = sharedkeys{ii};
        outMap(key) = [map1(key) map2(key)];
    end
end
end

Provides the desired outcome:

ans =

  6×2 cell array

    {'145'}    {[368.2000]}
    {'15' }    {[ 32.3000]}
    {'333'}    {1×2 double}
    {'34' }    {[178.4000]}
    {'6'  }    {[197.6000]}
    {'765'}    {[ 37.3000]}

>> newMap('333')

ans =

  327.2000   69.9000

Note that you'll need to set 'UniformValues' to false in your containers.map generation, otherwise you will receive errors if all of your values are scalar and you attempt to concatenate two keys together.

For example:

>> A = containers.Map('foo', 42);
>> A('foo') = [A('foo') 3.14]
Error using containers.Map/subsasgn
Specified value type does not match the type expected for this container.

>> A = containers.Map('foo', 42, 'UniformValues', false);
>> A('foo') = [A('foo') 3.14];
>> A('foo')

ans =

   42.0000    3.1400

Upvotes: 1

Related Questions