# Prepend 0 to sublists

My question is similar to this one, but my goal is to prepend a single 0 the each sublist, not incrementally many 0's.

The file I'm working is a CSV containing around 50K sublists of length 35.

I've tried to Riffle my Flatten[list,1] and then Partition it into properly sized sublists, but the result isn't pretty - I might have to add an offset parameter.

Also, I'm trying to learn how to use pure functions, so any suggestion using them will be of help!

-

lists = RandomInteger[{1, 9}, {4, 5}]

{{7, 4, 9, 9, 7},
{4, 2, 5, 5, 2},
{6, 5, 9, 2, 4},
{1, 9, 4, 7, 2}}

ArrayPad[lists, {{0, 0}, {1, 0}}]

{{0, 7, 4, 9, 9, 7},
{0, 4, 2, 5, 5, 2},
{0, 6, 5, 9, 2, 4},
{0, 1, 9, 4, 7, 2}}


There are of course many ways to do this.

Since you are interested in learning here are some others, more or less practical:

Prepend[#, 0]& /@ lists

Join[{0} & /@ lists, lists, 2]

{0, ##} & @@@ lists

lists /. {x__Integer} :> {0, x}

PadLeft[#, Dimensions@# + {0, 1}] &@lists


Rojo expressed doubt about the speed of ArrayPad. Here are some comparative timings using Packed Arrays, which one should use if speed is a concern:

lists = RandomInteger[99, {50000, 35}];

timeAvg =
Function[x,
Do[If[# > 1, Return[#/5^i]] & @@ Timing@Do[x, {5^i}], {i, 0, 15}],
HoldFirst];

Transpose@{ConstantArray[0, Length@#], Sequence @@ Transpose@#} &@lists // timeAvg

ArrayPad[lists, {{0, 0}, {1, 0}}] // timeAvg

Join[0 ~ConstantArray~ {Length@#, 1}, #, 2] &@lists // timeAvg

ArrayFlatten@{{0, lists}} // timeAvg


0.00604

0.0019968

0.001224

0.0010032

ArrayFlatten is the fastest, taking 82% as long as Join/ConstantArray and 50% as long as ArrayPad.

Now an unpackable array (strings):

lists = RandomChoice["a" ~CharacterRange~ "z", {50000, 35}];

Transpose@{ConstantArray[0, Length@#], Sequence @@ Transpose@#} &@
lists // timeAvg

ArrayPad[lists, {{0, 0}, {1, 0}}] // timeAvg

Join[0 ~ConstantArray~ {Length@#, 1}, #, 2] &@lists // timeAvg

ArrayFlatten@{{0, lists}} // timeAvg


0.023464

0.024088

0.024088

0.08236

Here ArrayFlatten takes 342% and 351% as long as the other methods, which are all about the same.

Conclusion: use ArrayFlatten when you're sure the data is a packed array of the same type as the value you are inserting; use Join or ArrayPad when you are not.

-
Nice use of the last (numeric) argument of Join. I hadn't used it before, but will have to try and remember that one in future as it's clearly quite advantageous. – Oleksandr R. Jul 6 '12 at 22:40
Thanks. I've checked the speeds too, and here's what I got. PadLeft is fastest, with the rule trailing behind. – CHM Jul 7 '12 at 4:14
@CHM Of those I think PadLeft was fastest for me too, but notice that the Join method you tested is not the same as the faster one with ConstantArray, and ArrayPad is also missing. By the way, the one you labeled obscure is actually the easiest for me to read, but then I'm a freak for ## and @@@ so {0, ##} & @@@ x is pretty much Nirvana. lol – Mr.Wizard Jul 7 '12 at 9:13
@CHM thanks for the Accept! – Mr.Wizard Jul 15 '12 at 1:25
Thanks to you. At first, {0, ##} & @@@ lists was obscure, but I was looking for a pure function, and was served. Now, it seems natural. – CHM Jul 15 '12 at 1:27
list = {{1, 2}, {3, 4}, {5, 6}};
Flatten /@ Tuples[{{0}, list}]

{{0, 1, 2}, {0, 3, 4}, {0, 5, 6}}

Join @@@ Tuples[{{{0}}, list}]


the latter method (thanks to kguler) is even faster than the former one.

These toys haven't been mentioned yet :

Join[ {0}, #] & /@ list

Flatten /@ ({0, #} & /@ list)

MapThread[ Join, {ConstantArray[{0}, Length @ list], list}]

Prepend[ #, 0] & /@ list

-
+1, creative one – Rojo Jul 6 '12 at 22:16
@Rojo Thanks, I wanted to use Tuples since sometimes it appears to be the best, look here e.g. mathematica.stackexchange.com/questions/4748/… – Artes Jul 6 '12 at 22:18
+1, or Join @@@ Tuples[{{{0}}, lists}]:)? – kglr Jul 6 '12 at 23:39
@kguler Thanks, I'll add this, seems even faster than Flatten /@ Tuples[{{0}, list}]. – Artes Jul 6 '12 at 23:54

One convenient method, originally due to Janus (see here):

list = {{1, 2}, {3, 4}, {5, 6}};

ArrayFlatten@{{0, list}}


giving

(* {{0, 1, 2}, {0, 3, 4}, {0, 5, 6}} *)

See here for some interesting comparisons by Timo

-

One (exotic) way is by using Flatten with its second argument (thanks to Oleksandr for fixing my Flatten). For example:

list= {{1, 2}, {3, 4}, {5, 6}};
Flatten[{ConstantArray[{0}, Length@#], #}, {{2}, {3, 1}}] &@list
(* {{0, 1, 2}, {0, 3, 4}, {0, 5, 6}} *)


See this answer by Leonid for a detailed explanation on how Flatten's second argument works.

However, this is "slow". Another possibility that's much faster than the above is

Transpose@{ConstantArray[0, Length@#], Sequence @@ Transpose@#} &@list


A rule based solution for doing the same would be:

list /. {x__?NumericQ} :> {0, x};


If your list isn't very large (and your CSV file is very modest), then this is perhaps the clearest in intent.

-
I beat you to the replacement rule. :^) Also, you may need to restrict it a bit... – Mr.Wizard Jul 6 '12 at 22:04
This question is your 80th in this tag, which means you get a silver tonight. Congrats! – R. M. Jul 6 '12 at 22:12
@OleksandrR. Thanks! I was trying that and observed that {{2}, {3}} and {{2}, {1}} gave similar, but differently grouped lists and couldn't figure out how to combine them other than with a Flatten/@. I'll add that in – R. M. Jul 6 '12 at 22:21
@Oleksandr your method however is considerably slower on the test used on my answer. – Mr.Wizard Jul 6 '12 at 22:24
@Oleksandr Leonid seems to have a better handle on that, but I have to rely on testing, memory, and On["Packing"]. Using Join over Flatten when possible is one of the heuristics I've picked up. – Mr.Wizard Jul 6 '12 at 23:01