2

My task now is want to construct a cell C which contain matrices which first dimensions are contained in a vector

n = [12 23 54].

While their second dimensions are fixed with

r = 3.

So, I want the cell C = {rand(12,3), rand(23,3), rand(54,3)}.

I know for-loop can serve my purpose as:

C=cell(3,1) % pre-allocation

for i = 1 : length(n)
    C{i} = rand(n(i),r);
end

May I know if I can do it smarter without using a for loop in Matlab? Thank you

Suever
  • 64,497
  • 14
  • 82
  • 101
nam
  • 215
  • 2
  • 11

3 Answers3

1

There's really no harm in using a for loop in this particular scenario (and in most cases where the only alternative is cellfun or arrayfun) as it is easier for MATLAB's JIT compiler to handle, but if you're really averse to a for loop you can use arrayfun combined within non-uniform output to give you the result you want.

C = arrayfun(@(x)rand(x, r), n, 'UniformOutput', false);

This may actually be slower than the for loop for the reasons mentioned above. But hey, it's one line so that's all that matters!

Community
  • 1
  • 1
Suever
  • 64,497
  • 14
  • 82
  • 101
  • Thank you so much and your introduction for the `arrayfun` command for me. – nam Jan 04 '17 at 15:48
  • "No harm in using a `for` loop" is a hugely over-general statement. In this context (cell arrays) there's no harm. In other contexts, such as numeric array computations, then there are a *few* special cases there's only marginal penalty to for loops, but usually massive advantages to avoiding them. – jez Jan 04 '17 at 15:49
  • @jez Believe me I'm well aware. I assumed that since I was answering a *specific* question it could be inferred that this comment was pertaining *directly* to the problem at hand. – Suever Jan 04 '17 at 16:01
  • 1
    @jez ...an equally over-generalized statement :) Can you provide an example to back it up? And what MATLAB version are you on? Because since R2015a the JIT has improved rather significantly regarding the performance of loops. There's ever fewer cases these days where I'd recommend against a `for`, so I'm curious to learn yours. – Rody Oldenhuis Jan 04 '17 at 16:01
  • @RodyOldenhuis Can't give proof because no access to 2015a. Am v. surprised to hear it. I have often seen spaghetti code that, when analysed and optimized properly, boils down to a couple of sequential matrix or tensor multiplications. Are you telling me that *matrix multiplication* can be done equally well with loops now? The marketing blurb on http://blogs.mathworks.com/loren/2016/02/12/run-code-faster-with-the-new-matlab-execution-engine/ claims it has "halved the execution time" of someone's code-but I've frequently seen vectorization speedups of 100x or 1000x relative to naive loops. – jez Jan 04 '17 at 16:22
  • @jez No, native BLAS or MKL speeds can of course never be attained with loops in a higher level language. But factors of 100 or more are becoming rare. Thing is, you just can't make blanket statements anymore, and the reasons to be wary-of-loops-by-default are quickly vanishing. A technological advancement is of course never a cure for plain bad programming. – Rody Oldenhuis Jan 04 '17 at 16:29
  • @RodyOldenhuis OK, but there are blanket statements and blanket statements. My original point (which the answerer seems to have taken on board) is that even unintentionally giving the impression that "it's OK now, things have changed, so you can feel free to use `for` loops for everything" will tend to propagate exactly the "plain bad programming" you mention. – jez Jan 04 '17 at 16:49
  • @jez I believe to opposite is true, so let's agree to disagree. – Rody Oldenhuis Jan 04 '17 at 17:23
  • 1
    @jez when it comes to `arrayfun` and `cellfun` there is always improvement when you use a simple `for`, at least in Matlab 2015a a newer. – EBH Jan 04 '17 at 18:56
1

for and while loops have their place, even in Matlab. You've probably been told to avoid them because vectorized operations are so much faster when you're iterating over the rows, columns or other dimensions of a packed numeric array. But with higher-level constructs, like cell arrays, there's often no advantage (and a readability penalty) to trying to do things all in neat quasi-vectorized statements. Your existing solution is probably the best approach.

jez
  • 14,867
  • 5
  • 37
  • 64
1

A shorter alternative, just for fun:

C = mat2cell(rand(sum(n),r), n,r)';

But a plain loop is almost certainly fastest in this case, because mat2cell uses a loop, as well as copious checks on its inputs.

Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96