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

share|improve this question

3 Answers 3

up vote 5 down vote accepted

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

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