Alternatives to Reap/Sow
1.
I would like to mention Table[]
in addition. In complicated situations, Reap
and Sow
maybe be a better alternative, but I've seen quite a bit of beginner's code that looks just like the Do
-AppendTo
loop above. In that particular case, Table[]
is superior both in speed and legibility. It's about 20 times faster than the Reap
version:
data = Table[RandomReal[x], {x, 0, 40000}];
(Asides: In some use cases, Map
may be an even better choice. Also, many functions are "vectorized" or have special cases for efficiently constructing arrays; for instance, RandomReal[1, 40001] * Range[0., 40000.]
produces nearly the same data 150 times faster than Reap
, the maximum relative error being less than 10^-12
-- learning to think computationally in terms of arrays can speed up code significantly.)
2.
Let me also add linked lists as an alternative (see also this answer by Leonid Shifrin). It is 5-10% faster than Reap
& Sow
.
data = {};
Do[data = {data, RandomReal[x]}, {x, 0, 40000}];
data = Flatten@data;
If the data is an multidimensional array, then we can structure the flattening operation by using a special head.
Block[{ll}, (* not necessary if ll is undefined *)
data = ll[];
Do[data = ll[data, RandomReal[x, 2]], {x, 0, 40000}];
data = List @@ Flatten[data, Infinity, ll];
]
Example timing:
SeedRandom[0]; (* for reproducible randomness *)
data = Reap[Do[Sow[RandomReal[x, 2]], {x, 0, 40000}]][[2, 1]]; // AbsoluteTiming
(* {0.097571, Null} *)
SeedRandom[0]; (* for reproducible randomness *)
dataLL = ll[];
(Do[dataLL = ll[dataLL, RandomReal[x, 2]], {x, 0, 40000}];
dataLL = List @@ Flatten[dataLL, Infinity, ll]); // AbsoluteTiming
(* {0.08676, Null} *)
data == dataLL
(* True *)