问题
I want to create a matrix like
A = [0 0 0 0 1;
0 0 0 1 1;
0 0 0 1 1;
0 0 0 1 1;
0 0 1 1 1;
0 1 1 1 1]
based on a vector indicating how many '0's should precede '1's on each row:
B = [4 3 3 3 2 1]
Is there a loopless way to do this ?
回答1:
You don't mention in your question how the horizontal size of the array should be defined (the number of ones).
For predefined width you can use this code:
width = 5;
A = cell2mat(arrayfun(@(x) [ zeros(1,x), ones(1,width-x) ], B, 'UniformOutput', false)');
If you want that A has minimal width, but still at least one 1 in every row:
A = cell2mat(arrayfun(@(x) [ zeros(1,x), ones(1,max(B)+1-x) ], B, 'UniformOutput', false)');
回答2:
A shorter “old-school” way to achieve this without a loop would be as follows:
A = repmat(B',1,max(B)+1)<repmat([1:max(B)+1],size(B,2),1)
If you want to have a minimum number of ones
min_ones=1; %or whatever
A = repmat(B',1,max(B)+min_ones)<repmat([1:max(B)+min_ones],size(B,2),1)
I don’t know how this compares speedwise to @nrz’s approach (I’ve only got Octave to hand right now), but to me it's more intuitive as it’s simply comparing a max(B) + min_ones * column tiling of B:
4 4 4 4 4
3 3 3 3 3
3 3 3 3 3
3 3 3 3 3
2 2 2 2 2
1 1 1 1 1
with a row tiling of [1 : max(B) + min_ones]
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
To generate:
A =
0 0 0 0 1
0 0 0 1 1
0 0 0 1 1
0 0 0 1 1
0 0 1 1 1
0 1 1 1 1
回答3:
This requires only one line, and seems to be faster than previous solutions based on repmat or arrayfun:
%// Example data
ncols = 5;
B = [4 3 3 3 2 1];
%// Generate A
A = bsxfun(@gt, 1:ncols, B(:));
来源:https://stackoverflow.com/questions/10258448/matrix-creation-octave-matlab-loopless-solution-request