creating a vector from a(:) : b(:) , but one for each index without using loops.

I have two vectors a=[1,2,3] and b=[6,4,9]. My goal is to generate this(see below) without the use of foor loops (a single command line);
result=[a(1):b(1),a(2):b(2),a(3):b(3)];
The problem is that a and b is varying in size (but size(a)=size(b)=[1,N]).
I`ve tried
result=[a(:):b(:)];
and other variations, but it doesnt do the job. Any idea of how i can achieve this?

 Accepted Answer

a=[1,2,3];
b=[6,4,9];
result = cell2mat(arrayfun(@(x,y)x:y,a,b,'un',0));
ADD
a = randi(150,32,4,4,4); % your 4-D array
idx = {1:32,3,2,1}; % your array with indexs
[i1,i2,i3,i4] = ndgrid(idx{:});
i1 = cell(1,4);
[i1{:}] = ndgrid(idx{:});
result = a(sub2ind(size(a),i1{:}));

8 Comments

Indeed this answers my question. But i failed to specify something i think. I need it to go fast. The whole point of creating this vector is to use it as an index in a 4-D matrix, to avoid using loops to index it. (basicly i have a dim= [32,4,4,4] matrix, and i have another dim=[4,4,4] to be used as indexing. if the indexing matrix is [3,2,1] i want to extract (:,3,2,1) from the 4-D matrix. So my idea is to use linear indexing by multiplying the idx matrix with the (d3)(d2)(d1),(d2)(d1) and so forth, and then sum the elements row wize to create an index vector, and then use this index vector to create something like: so that idx(1)=(l-1)(d3)(d2)(d1)+(k-1)(d2)(d1) etc..
[idx(1):idx(1)+32 , idx(2):idx(2)+32 .... ] etc. The i can extract the elements i want from the original matrix using
4d_matrix(result_from_idx_vector);
instead of:
for i=1:size(3d_m,1)
result(1+(i-1)*32:i*32)=4d_matrix(:,3d_(i,1),3d_m(i,2),3d_m(i,3));
end
But by using arrayfun and cell2mat i suspect it will take even longer then the original for loop.
Suspect... Have you tested it? You could also try ind2sub(). It does what you ask for.
Sorry, the indexing matrix is not of dim=[4,4,4]. Its a N*3 matrix.
time for 1021 calls:
the for loop -> 3.21sec
idx=cell2mat(arrayfun(@(x,y)x:y,idx,idx2,'un',0)); ->10.61 sec
and ind2sub() wouldnt help, but maybe sub2ind.. But then again sub2ind would only give me the first of each index and i would end up with the same problem, because i need to extract 32 elements for each index(or i would have to loop it, correct me if im wrong). That is why i have arranged the 4-D matrix so that its of size [32,4,4,4]. Becuase then i can just increment 1 32 times for each index i get from the idx matrix Xn.
Here is my code :
N=length(Xn);
psi=zeros(1,N*Ts); %Ts=32
for i=1:N
psi(1+(i-1)*Ts:i*Ts) = psi_table(:,Xn(i,1),Xn(i,2),Xn(i,3));
end
I have also tried using cells to store this "psi_table". But it seems matlab uses even more time to nest up the cell. So the matrix is better. perhaps i should just accept that this will take some time, but it feels so unnecessary since its supposed to be a "look-up-table" :/
Hmm.. ADD might work yes. The question to be answered though is whether ndgrid and sub2ind will eat the time im gaining by not indexing in a loop :P Ill run some tests with this vs my old solution and also ill try to create my original idx vector in a loop to see what is fastest! Im also feeling there might be a solution with repmat to this problem.
Thanks for your time everyone , really appreciate it!
@Kjetil87, probably not, ind2sub is slow and and gets much slower for big data.
Use the for-loop just make pull out as many computations as you can which it looks like you've done already.
for those interested i found a way that works.
siz=size(psi_table);
Xn(:,3)=(Xn(:,3)-1)*prod(siz(1:3)); % (l-1)(d3)(d2)(d1)
Xn(:,2)=(Xn(:,2)-1)*prod(siz(1:2)); % (k-1)(d2)(d1)
Xn(:,1)=(Xn(:,1)-1)*siz(1); % (j-1)(d1)
idx=sum(Xn,2)+1; % +1 to start at 4D_matrix(1,j,k,l)
idx_V=repmat(0:31,length(idx),1)+repmat(idx,1,32);
idx_V=idx_V';
idx_V=idx_V(:)';
psi=psi_table(idx_V);
% all operations but the repmat line is basicly 0 cost. And repmat is considerably faster then the for loop indexing ( total of aprox 0.6secs vs 6secs for 2263 calls with a big matrix )

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!