# List Manipulation

I would like to transform the following list

data={{0,A1,1},{1,C1,2},{1,C2,3},{3,C4,1},{0,A2,1},{1,C2,1},{0,A1,4},{1,C1,1},{2,C2,1}}


into another list like this

output={{A1,1,0,A1,1},{A1,1,1,C1,2},{A1,1,1,C2,3},{A1,1,3,C4,1},{A2,1,0,A2,1},{A2,1,1,C2,1},{A1,4,0,A1,4},{A1,4,1,C1,1},{A1,4,2,C2,1}}


Basically, the first column indicates the level,0 being the head level of a bill of material and would like to put the header item and header quantity as columns besides the components for easier computation further along.

Thanks.

-
This could use a better title... – J. M. Nov 3 '12 at 5:17
Indeed @J.M., the title should be better, but couldn't come up with one. What would your recommendation be? – PatoCriollo Nov 3 '12 at 13:20
Well, the real problem that you're trying to solve ought to be reflected in the title... – J. M. Nov 3 '12 at 13:32

The first thing you should do is collect all the elements under a single header into their own sublists. Assuming the "levels" are always in increasing order, this will do the job:

sublists = Split[data, First@#1 <= First@#2 &]
(* {{{0, A1, 1}, {1, C1, 2}, {1, C2, 3}, {3, C4, 1}},
{{0, A2, 1}, {1, C2, 1}},
{{0, A1, 4}, {1, C1, 1}, {2, C2, 1}}} *)


Then for each sublist, you can just take its header and join it to all its elements.

formatted = Function[list, Join[Rest@First@list, #] & /@ list] /@ sublists
(* {{{A1, 1, 0, A1, 1}, {A1, 1, 1, C1, 2}, {A1, 1, 1, C2, 3}, {A1, 1, 3, C4, 1}},
{{A2, 1, 0, A2, 1}, {A2, 1, 1, C2, 1}},
{{A1, 4, 0, A1, 4}, {A1, 4, 1, C1, 1}, {A1, 4, 2, C2, 1}}} *)


In the end you probably also want to flatten the sublists.

output = Flatten[formatted, 1]
(* {{A1, 1, 0, A1, 1}, {A1, 1, 1, C1, 2}, {A1, 1, 1, C2, 3}, {A1, 1, 3, C4, 1},
{A2, 1, 0, A2, 1}, {A2, 1, 1, C2, 1}, {A1, 4, 0, A1, 4}, {A1, 4, 1, C1, 1},
{A1, 4, 2, C2, 1}} *)


Of course, all of this can be pulled into a single expression if you prefer:

output = Flatten[
Function[list, Join[Rest@First@list, #] & /@ list] /@
Split[data, First@#1 <= First@#2 &], 1]

-

Guessing the "header" data from the two lists in your question, and making non-numeric elements strings,

data = {{0, "A1", 1}, {1, "C1", 2}, {1, "C2", 3}, {3, "C4", 1}, {0,"A2", 1},
{1, "C2", 1}, {0, "A1", 4}, {1, "C1", 1}, {2, "C2", 1}};
headers = {{"A1", 1}, {"A1", 1}, {"A1", 1}, {"A1", 1}, {"A2", 1}, {"A2", 1},
{"A1", 4}, {"A1", 4}, {"A1", 4}};


you can use

MapThread[Join, {headers, data}];
(* or *)  Join @@@ Thread[{headers, data}]
(* or *)  Flatten /@ Thread@{headers, data}
(* or *)  Transpose[Flatten[Transpose /@ {headers, data}, 1]]
(* or *)  Thread[Flatten[Transpose /@ {headers, data}, 1]]


All give

{{"A1", 1, 0, "A1", 1}, {"A1", 1, 1, "C1", 2}, {"A1", 1, 1, "C2", 3},
{"A1", 1, 3, "C4", 1}, {"A2", 1, 0, "A2", 1}, {"A2", 1, 1, "C2", 1},
{"A1", 4, 0, "A1", 4}, {"A1", 4, 1, "C1", 1}, {"A1", 4, 2, "C2", 1}}

-
 I think the header is supposed to be the latest entry with first element 0. – Rahul Narain Nov 3 '12 at 7:43 @Rahul, I think you are right ... and that makes it a much more interesting question. – kguler Nov 3 '12 at 8:58 @Rojo/@kgluger/@Rahul, thanks so much for taking a stab at the problem. Just to give some context, the toy problem below is an overall simplification of importing and processing some ascii dumps of 200+ report. In the files you would have a header structure, and then a list of variable number components, header and components with each with its own field structure. I was successful in manipulating the files and dumping everything into a single list and this is where I got stuck. It is still very difficult for me to get away from procedural language structure, – PatoCriollo Nov 3 '12 at 13:27 which is what I finally used to get things done quickly, but I want to avoid the use of do's and for's in Mathematica. – PatoCriollo Nov 3 '12 at 13:29

If what @kguler interpreted is correct, then you could do

Rest@FoldList[
Join[If[First@#2 == 0, Rest@#2, #1~Take~2], #2] &, {Null, "Default", Indeterminate},
data]

-