3
$\begingroup$

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?

$\endgroup$
5
$\begingroup$

ConstantArray is your friend.

Flatten[ConstantArray[#, 3] & /@ {{a}, {b}, {c}}, 1]
{{a}, {a}, {a}, {b}, {b}, {b}, {c}, {c}, {c}}
$\endgroup$
4
$\begingroup$

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}}

$\endgroup$
  • $\begingroup$ Nice idea. I added an extension assuming you wouldn't mind. $\endgroup$ – Mr.Wizard Aug 7 '14 at 18:15
  • $\begingroup$ @Mr.Wizard. I don't mind your edits at all. Nice addition by the way. Thanks. $\endgroup$ – RunnyKine Aug 7 '14 at 18:17
  • $\begingroup$ Unfortunately this method proves to be one of the slower ones. See my updated answer. (The colors are hard to distinguish but f9 is the line third from the top, meaning third slowest.) $\endgroup$ – Mr.Wizard Aug 7 '14 at 18:52
  • $\begingroup$ @Mr.Wizard. Oh well, we can't win all the time :) $\endgroup$ – RunnyKine Aug 7 '14 at 18:54
4
$\begingroup$

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]

Benchmarks

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
]

enter image description here

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
]

enter image description here

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.

$\endgroup$
  • $\begingroup$ +1 for Flatten. BTW my MMA 10 could not generate BenchmarkPlot. All I got was this. $\endgroup$ – seismatica Aug 7 '14 at 19:20
  • $\begingroup$ @seismatica Thanks for the vote. Very strange error; I guess BenchmarkPlot has some bugs to work out. The package is very new and rough in spots. $\endgroup$ – Mr.Wizard Aug 7 '14 at 19:32
  • $\begingroup$ Is this a built-in package or do I have to download it somewhere? $\endgroup$ – seismatica Aug 7 '14 at 19:32
  • $\begingroup$ @seismatica It is built into version 10 and should be loaded by the line Needs["GeneralUtilities`"] $\endgroup$ – Mr.Wizard Aug 7 '14 at 19:39
2
$\begingroup$

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]
$\endgroup$
  • 1
    $\begingroup$ For large n, Table will slow down a bit. $\endgroup$ – rcollyer Aug 7 '14 at 13:43
1
$\begingroup$

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}}*)
$\endgroup$
0
$\begingroup$
Flatten[PadLeft[{#}, 3, {#}] & /@ {{a}, {b}, {c}}, 1]
$\endgroup$
0
$\begingroup$

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}]]
$\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.