I'd like to a create a list from A = {{a}, {b}, {c}}
by taking each elements n
times in the following form:
B={{a},{a},{a},{b},{b},{b},{c},{c},{c}}
Any idea?
Mathematica Stack Exchange is a question and answer site for users of Wolfram Mathematica. It only takes a minute to sign up.
Sign up to join this communityConstantArray
is your friend.
Flatten[ConstantArray[#, 3] & /@ {{a}, {b}, {c}}, 1]
{{a}, {a}, {a}, {b}, {b}, {b}, {c}, {c}, {c}}
Here is an interesting approach:
We first define a helper function:
f[x_] := Sequence[x, x, x]
Then it's just a matter of mapping it on A
to create B
:
A = {{a}, {b}, {c}};
f /@ A
{{a}, {a}, {a}, {b}, {b}, {b}, {c}, {c}, {c}}
We could also use a SubValues (or "operator form") definition for flexible replication:
g[n_][x_] := Sequence @@ ConstantArray[x, n];
g[3] /@ A
{{a}, {a}, {a}, {b}, {b}, {b}, {c}, {c}, {c}}
MapAt[g[3], A, 2]
{{a}, {b}, {b}, {b}, {c}}
f9
is the line third from the top, meaning third slowest.)
$\endgroup$
Aug 7, 2014 at 18:52
My additions, duplicating the entire array first:
ConstantArray[A, 3] ~Flatten~ {2, 1}
Join @@ (ConstantArray[A, 3]\[Transpose])
Join @@ Thread @ ConstantArray[A, 3]
Sequence ~MapThread~ ConstantArray[A, 3]
Timings for all methods in the order they were posted, tested only for triplication on a packed array.
f1[array_] :=
Composition[Flatten[#, 1] &, Replace[#, x_ :> ConstantArray[x, 3], 1] &][array]
f2[A_] := Flatten[ConstantArray[#, 3] & /@ A, 1]
f3[A_] := Flatten[A /. {x_} :> {{x}, {x}, {x}}, 1]
f4[A_] := Flatten[{#, #, #} & /@ A, 1]
f5[A_] := ConstantArray[A, 3] ~Flatten~ {2, 1}
f6[A_] := Join @@ (ConstantArray[A, 3]\[Transpose])
f7[A_] := Join @@ Thread @ ConstantArray[A, 3]
f8[A_] := Sequence ~MapThread~ ConstantArray[A, 3]
f[x_] := Sequence[x, x, x];
f9[A_] := f /@ A
gen = RandomInteger[99, {#, 1}] &;
Needs["GeneralUtilities`"]
BenchmarkPlot[
{f1, f2, f3, f4, f5, f6, f7, f8, f9},
gen, 2^Range[20], "IncludeFits" -> True
]
All methods have the same order of complexity but there is a clear winner for speed:
f5[A_] := ConstantArray[A, 3] ~Flatten~ {2, 1}
Running the tests again with unpackable data:
gen2 = "a" ~CharacterRange~ "z" ~RandomChoice~ {#, 1} &;
BenchmarkPlot[
{f1, f2, f3, f4, f5, f6, f7, f8, f9},
gen2, 2^Range[20], "IncludeFits" -> True
]
The winners are f6
, f7
, and f5
in order, with f6
and f7
only slightly ahead of f5
which does not justify their use given f5
's large margin of performance on packed data.
Flatten
. BTW my MMA 10 could not generate BenchmarkPlot
. All I got was this.
$\endgroup$
Aug 7, 2014 at 19:20
BenchmarkPlot
has some bugs to work out. The package is very new and rough in spots.
$\endgroup$
Aug 7, 2014 at 19:32
Needs["GeneralUtilities`"]
$\endgroup$
Aug 7, 2014 at 19:39
Just for variation, using replacement rules we have for small n:
Flatten[{{a}, {b}, {c}} /. {x_} :> {{x},{x},{x}}, 1]
and for large n :
Flatten[{{a}, {b}, {c}} /. {x_} :> Table[{x}, {3}], 1]
Use Replace
with levelspec = 1
createArray[array_, n_] := Composition[
Flatten[#, 1] &,
Replace[#, x_ :> ConstantArray[x, n], 1] &
][array]
Check function:
createArray[{{a},{b},{c}}, 3]
(*{{a},{a},{a},{b},{b},{b},{c},{c},{c}}*)
Different approaches (just for fun)
Join @@ (ComposeList[Table[# &, {2}], #] & /@ A)
Join @@ (Nest[Append[#, First@#] &, {#}, 2] & /@ A)
Join @@ (NestList[# &, #, 2] & /@ A)
Fold[Riffle[#1, A, {#2, -1, #2}] &, A, {2, 3}]
Join @@ MapThread[List, Table[A, {3}]]