# How to avoid for loops when generating index arrays?

1 view (last 30 days)

Show older comments

I often find myself coding nested for loops to generate vectors of integer indices. For example:

n = 4;

i = 1;

for L = 0:n

for M = -L:L

l(i) = L;

m(i) = M;

i = i+1;

end

end

All I need are the vectors "l" and "m". I can preallocate to save some speed, but my real problem is having to use the for loops as sometimes the index vectors I need to create have many more nested for loops whose (note that the inner loop index depends on the outer loop index).

Is there a simple way to avoid using loops to generate index vectors like these?

##### 0 Comments

### Accepted Answer

Matt J
on 30 Apr 2013

Here's another method, less memory consuming than NDGRID

mm=sparse(-n:n);

ll=sparse(0:n);

map=bsxfun(@le,abs(mm.'),ll);

idx=nonzeros(bsxfun(@times,map,1:length(ll) ));

l=full(ll(idx));

idx=nonzeros(bsxfun(@times,map,(1:length(mm)).')) ;

m=full(mm(idx));

##### 0 Comments

### More Answers (5)

Roger Stafford
on 30 Apr 2013

Edited: Matt J
on 30 Apr 2013

For your particular problem you can do this:

M = (0:n*(n+2))';

L = floor(sqrt(M));

M = M-L.*(L+1);

(I've used uppercase letters, 'L' and 'M', in place of your lowercase 'l' and 'm'.)

As with Matt Kindig, I am not sure this will be any faster than your for-loops. Time it with a large value for n and see.

##### 0 Comments

Matt J
on 30 Apr 2013

Edited: Matt J
on 30 Apr 2013

Here's a way to do it using NDGRID. It's not apriori obvious whether for loops would or would not be faster. It depends what you plan to reuse.

[mg,lg]=ndgrid(-n:n,0:n);

idx=abs(mg)<=lg;

l=lg(idx).',

m=mg(idx).',

##### 6 Comments

Matt J
on 1 May 2013

Edited: Matt J
on 2 May 2013

Sean de Wolski
on 30 Apr 2013

Edited: Sean de Wolski
on 30 Apr 2013

doc meshgrid

doc ndgrid %?

:)

And of course, depending on your application, two nested for-loops or bsxfun() might be better.

##### 2 Comments

Sean de Wolski
on 30 Apr 2013

Just use the for-loops, they'll be the fastest by far. If you want to disguise it, write a function that takes L and M and returns l and m.

cellfun and arrayfun are slow and converting between cells and numeric types is slow. The above with preallocation will be pretty quick.

Matt Kindig
on 30 Apr 2013

It's kind of hack-y, but it gives the same output as your original posting:

n=4;

l = cell2mat(arrayfun(@(x) x*ones(1,2*x+1), 0:n, 'uni', false));

m= cell2mat( arrayfun(@(x) (-x:1:x), 0:n, 'uni', false));

Keep in mind that this may very well be slower than for-loops--I haven't done any timing comparisons.

##### 0 Comments

Matt J
on 1 May 2013

Edited: Matt J
on 1 May 2013

Here's a way to eliminate one nested loop

l=cell(1,n+1);

m=l;

for L=0:n

i=L+1;

m{i}=-L:L;

l{i}=m{i};

l{i}(:)=L;

end

l=[l{:}],

m=[m{:}],

##### 2 Comments

Sean de Wolski
on 1 May 2013

### See Also

### Categories

### Products

### Community Treasure Hunt

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

Start Hunting!