5
$\begingroup$

If I want to have a nested list like 10 times of {1,2..,9,10}:

{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1,
2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 
2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2,
3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 
3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}

I can easily understand that Table[i,{i,1,10}] will give me a sub list {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, so I can imagine if I want to have ten same sub lists I need to apply this table function for ten times, so I use Table[Table[i,{i,1,10}],{10}] to get what I want.

But I know for the language of Mathematica, things could happen a lot of miraculous than I thought, there must be some more elegant ways to manipulate lists. My question is asking do you think 'Table[Table[expr, ],{conditions}]' stuff are good implementations in terms of efficiency in my case?

$\endgroup$
2
  • 2
    $\begingroup$ Table is likely pretty efficient, barring the lists having special structure (like the example you showed). However, you don't need to nest Tables: You can just do Table[i, {10}, {i, 1, 10}], for instance. $\endgroup$
    – march
    Jan 5, 2018 at 20:59
  • $\begingroup$ Thanks for telling me this method! $\endgroup$
    – cj9435042
    Jan 5, 2018 at 21:28

3 Answers 3

8
$\begingroup$

Extract is much faster than all alternatives posted/mentioned so far.

Extract[{Range @ 5}, ConstantArray[{1}, 5]] // TeXForm

$\left( \begin{array}{ccccc} 1 & 2 & 3 & 4 & 5 \\ 1 & 2 & 3 & 4 & 5 \\ 1 & 2 & 3 & 4 & 5 \\ 1 & 2 & 3 & 4 & 5 \\ 1 & 2 & 3 & 4 & 5 \\ \end{array} \right)$

Timings: Using @BobHanlon's timing setup:

n = 10^3;
{t1 = AbsoluteTiming[tab1 = Table[i, {n}, {i, 1, n}];][[1]], 
 t2 = AbsoluteTiming[tab2 = Table[Range[n], {n}];][[1]], 
 t3 = AbsoluteTiming[tab3 = Table[Table[i, {i, 1, n}], {n}];][[1]], 
 t4 = AbsoluteTiming[tab4 = ConstantArray[Range[n], n];][[1]],
 t5 = AbsoluteTiming[tab5 = Extract[{Range[n]}, ConstantArray[{1}, n]];][[1]]}

{5.844533, 0.104275, 0.750996, 0.095255, 0.001003}

% / t5 // Round[#, 1]&

{5825, 104, 748, 95, 1}

 tab1 == tab2 == tab3 == tab4 == tab5

True

For n = 10^4; we get

{t1, t2, t3, t4, t5}

{24.885165, 1.786752, 2.813479, 0.323860, 0.001003}

% / t5 // Round[#, 1]&

{24801, 1781, 2804, 323, 1}

Update: Part + ConstantArray

{Range[5]}[[ConstantArray[1, 5]]] // TeXForm

$\left( \begin{array}{ccccc} 1 & 2 & 3 & 4 & 5 \\ 1 & 2 & 3 & 4 & 5 \\ 1 & 2 & 3 & 4 & 5 \\ 1 & 2 & 3 & 4 & 5 \\ 1 & 2 & 3 & 4 & 5 \\ \end{array} \right)$

This is as fast or faster than Extract:

n = 10^4;
{t5 = AbsoluteTiming[tab5 = Extract[{Range[n]}, ConstantArray[{1}, n]];][[1]],
 t6 = AbsoluteTiming[tab6 = {Range[n]}[[ConstantArray[1, n]]];][[1]]}

{0.003003, 0.001006}

tab5 == tab6

True

$\endgroup$
3
  • $\begingroup$ Very nice comparison! $\endgroup$
    – cj9435042
    Jan 6, 2018 at 4:54
  • $\begingroup$ Wow, I am quite surprised that ConstantArray[Range[n], n] performs so badly. $\endgroup$ Jan 7, 2018 at 18:13
  • $\begingroup$ @HenrikSchumacher, I wasn't expecting this either. $\endgroup$
    – kglr
    Jan 7, 2018 at 20:12
7
$\begingroup$

The list can be constructed by more specific functions than Table:

ConstantArray[Range[10], 10]

(*{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1,
2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 
2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2,
3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 
3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}*)
$\endgroup$
1
  • 5
    $\begingroup$ Time comparison with n=10^4: Table[Table[i, {i, 1, n}], {n}]; // RepeatedTiming gave 0.84, and ConstantArray[Range[n], n]; // RepeatedTiming gave 0.076. $\endgroup$
    – corey979
    Jan 5, 2018 at 19:26
3
$\begingroup$

The relative timings can change significantly with n

n = 10^2;

{t1 = RepeatedTiming[tab1 = Table[i, {n}, {i, 1, n}];][[1]],
 t2 = RepeatedTiming[tab2 = Table[Range[n], {n}];][[1]],
 t3 = RepeatedTiming[tab3 = Table[Table[i, {i, 1, n}], {n}];][[1]], 
 t4 = RepeatedTiming[tab4 = ConstantArray[Range[n], n];][[1]]}

(* {0.00069, 0.00008, 0.00069, 4.*10^-6} *)

%/t4 // N

(* {180.947, 19.9453, 182.789, 1.} *)

Note that the nested tables is the slowest.

Verifying that all four approaches give the same result

tab1 === tab2 === tab3 === tab4

(* True *)

Increasing n

n = 10^3;

{t1 = RepeatedTiming[tab1 = Table[i, {n}, {i, 1, n}];][[1]],
 t2 = RepeatedTiming[tab2 = Table[Range[n], {n}];][[1]],
 t3 = RepeatedTiming[tab3 = Table[Table[i, {i, 1, n}], {n}];][[1]], 
 t4 = RepeatedTiming[tab4 = ConstantArray[Range[n], n];][[1]]}

(* {0.064, 0.010, 0.0099, 0.00075} *)

%/t4 // N

(* {85.5733, 13.388, 13.181, 1.} *)

Note that the nested tables is no longer the slowest.

tab1 === tab2 === tab3 === tab4

(* True *)

Further increasing n

n = 10^4;

{t1 = RepeatedTiming[tab1 = Table[i, {n}, {i, 1, n}];][[1]],
 t2 = RepeatedTiming[tab2 = Table[Range[n], {n}];][[1]],
 t3 = RepeatedTiming[tab3 = Table[Table[i, {i, 1, n}], {n}];][[1]], 
 t4 = RepeatedTiming[tab4 = ConstantArray[Range[n], n];][[1]]}

(* {10.3, 1.8, 0.93, 0.51} *)

%/t4 // N

(* {20.1379, 3.51058, 1.83164, 1.} *)

tab1 === tab2 === tab3 === tab4

(* True *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.