1
votes

I have an arbitrary matrix, a = [1, 0, 0, 1].

I want to replace every 0 value with the values of another matrix b = [1, 2, 3], and every 1 value with the value of yet another matrix c = [3, 4, 5].

I would therefore end up with the matrix [3, 4, 5, 1, 2, 3, 1, 2, 3, 3, 4, 5].

I've tried finding the indices of the 0 and 1 values and replacing the values at those indices with b and c, but this isn't allowed since they aren't the same size. Is there any simple way of achieving this?

2
Will b and c always have the same size? - Luis Mendo

2 Answers

3
votes

Given

a = [1, 0, 0, 1];
b = [1, 2, 3];
c = [3, 4, 5];

Let's first take the arrays we want in the final matrix and put them in a cell array:

parts = {b, c}
parts =
{
  [1,1] =
     1   2   3
  [1,2] =
     3   4   5
}

The goal is to use the values of a as indices into parts, but to do that we need all of the values to be positive from 1 to some n (if there are missing values it'll take a bit more work). In this case we can just increment a:

a_inds = a + 1
a_inds =
   2   1   1   2

Now we can get a new cell array by doing parts(a_inds), or a matrix by adding cell2mat:

result = cell2mat(parts(a_inds))
result =
   3   4   5   1   2   3   1   2   3   3   4   5
0
votes

This can also be done with a key:value map.

a = [1, 0, 0, 1];
b = [1, 2, 3];
c = [3, 4, 5];

keyset = [1,0];
valueset = {b,c};

mapobj = containers.Map(keyset,valueset);
new_vec = [];
for i =1:length(a)
    new_vec(length(new_vec)+1:length(new_vec)+length(mapobj(a(i))))= mapobj(a(i));
end

1 is mapped to b and 0 mapped to c. The for loop iterates over a building an ever longer vector containing the mapped values.

This code will allow for non-sequential keys such that 37 could be added and mapped to another vector, whereas in the previous answer you would have to map 2 to the next vector in order for the code not to break.