Andreas
Andreas

Reputation: 7550

Neat way to loop with both index and value in Matlab

A lot of my loops look like this:

items = [3,14,15,92];
for item_i = 1:numel(items)
    item = items(item_i);
    % ...
end

This looks a bit messy to me. Is there some loop construct that lets me loop through the items and carry the index at the same time?

I'm looking for a syntax along the lines of for item_i as item = items or for [item_i item] = items.

Upvotes: 8

Views: 448

Answers (4)

grantnz
grantnz

Reputation: 7423

Similar to Chris Taylor's answer you could do this:

function [ output ] = Enumerate( items )
output = struct('Index',num2cell(1:length(items)),'Value',num2cell(items));
end


items = [3,14,15,92];
for item = Enumerate(items)
   item.Index
   item.Value
end

The Enumerate function would need some more work to be general purpose but it's a start and does work for your example.

This would be okay for small vectors but you wouldn't want to do this with any sizable vectors as performance would be an issue.

Upvotes: 7

wakjah
wakjah

Reputation: 4551

I will occasionally do something like this

arr = {'something', 'something else'};
arrayfun(@(x, y)sprintf('%s (item %i)', x{:}, y), arr, 1:length(arr), ...
    'UniformOutput', false)

But this is only useful in very specific situations (specifically, those same situations where you would use arrayfun to shorten syntax), and to be honest the way you were doing it initially is probably better for most cases - anything else will probably obfuscate your intent.

Upvotes: 2

Chris Taylor
Chris Taylor

Reputation: 47382

I believe that there is no way of doing this. A trick I've used in the past is to exploit the fact that Matlab loops over the columns of a matrix, so you can define a function enumerate that adds an index row to the top of a matrix:

function output = enumerate(x)
   output = [1:size(x,2); x];
end

and then use it like this:

for tmp = enumerate(items)
    index = tmp(1);
    item  = tmp(2:end);
end

but that's not really any better than what you were doing originally. It would be nice if à la Python you could so something like

for [index,item] = enumerate(items)
    # loop body
end

where enumerate is a function that returns two matrices of the same length, but... you can't.

Upvotes: 5

Stewie Griffin
Stewie Griffin

Reputation: 14939

Will this work for you?

k = 0;
for ii = items
  k = k + 1;  %% The index
  item = ii;  
  % ...
end

Hope it helps.

Upvotes: 1

Related Questions