creating a vector from a(:) : b(:) , but one for each index without using loops.
You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Show older comments
0 votes
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
Andrei Bobrov
on 1 Nov 2012
Edited: Andrei Bobrov
on 1 Nov 2012
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
kjetil87
on 1 Nov 2012
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.
José-Luis
on 1 Nov 2012
Suspect... Have you tested it? You could also try ind2sub(). It does what you ask for.
kjetil87
on 1 Nov 2012
Sorry, the indexing matrix is not of dim=[4,4,4]. Its a N*3 matrix.
kjetil87
on 1 Nov 2012
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" :/
Andrei Bobrov
on 1 Nov 2012
see ADD
kjetil87
on 1 Nov 2012
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!
Sean de Wolski
on 1 Nov 2012
@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.
kjetil87
on 1 Nov 2012
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 )
More Answers (0)
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Tags
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)