Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question

7 Answers 7

ConstantArray is your friend.

Flatten[ConstantArray[#, 3] & /@ {{a}, {b}, {c}}, 1]
{{a}, {a}, {a}, {b}, {b}, {b}, {c}, {c}, {c}}
share|improve this answer

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

share|improve this answer
    
Nice idea. I added an extension assuming you wouldn't mind. –  Mr.Wizard Aug 7 at 18:15
    
@Mr.Wizard. I don't mind your edits at all. Nice addition by the way. Thanks. –  RunnyKine Aug 7 at 18:17
    
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.) –  Mr.Wizard Aug 7 at 18:52
    
@Mr.Wizard. Oh well, we can't win all the time :) –  RunnyKine Aug 7 at 18:54

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.

share|improve this answer
    
+1 for Flatten. BTW my MMA 10 could not generate BenchmarkPlot. All I got was this. –  seismatica Aug 7 at 19:20
    
@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. –  Mr.Wizard Aug 7 at 19:32
    
Is this a built-in package or do I have to download it somewhere? –  seismatica Aug 7 at 19:32
    
@seismatica It is built into version 10 and should be loaded by the line Needs["GeneralUtilities`"] –  Mr.Wizard Aug 7 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]
share|improve this answer
1  
For large n, Table will slow down a bit. –  rcollyer Aug 7 at 13:43

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}}*)
share|improve this answer
Flatten[PadLeft[{#}, 3, {#}] & /@ {{a}, {b}, {c}}, 1]
share|improve this answer

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}]]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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