# Non-canonical re-ordering of nested lists

I have some data in the form:

 data = {{{d, 0.68}, {g, 0.88}, {h, 0.23}, {e, 0.15}, {b, 0.46}, {a, 0.07}},
{{d, 0.86}, {c, 0.99}, {b, 0.21}},
{{c,0.83}, {h, 0.63}, {f, 0.11}},
{{d, 0.31}, {g, 0.65}, {e, 0.88}, {a, 0.70}},
{{d, 0.58}, {g, 0.09}, {c, 0.66}, {b, 0.18}, {a, 0.15}}}


These data are essentially related to each other in the following way:

{{{d, d1}, {g, g1}, {h, h1}, {e, e1}, {b, b1}, {a, a1}},
{{d, d2}, {c, c2}, {b, b2}},
{{c, c3}, {h, h3}, {f, f3}},
{{d, d4}, {g, g4}, {e, e4}, {a, a4}},
{{d, d5}, {g, g5}, {c, c5}, {b, b5}, {a, a5}}}


The ordering of elements within each second level list is:

order1 = {d, g, c, h, e, f, b, a}


I want to collect the second term of each third level pair and rearrange the elements according to a different order:

order2 = {b, h, d, a, e, f, c, g}


so that I end up with something like:

{{b1, h1, d1, a1, e1, f1, c1, g1},
{b2, h2, d2, a2, e2, f2, c2, g2},
{b3, h3, d3, a3, e3, f3, c3, g3},
{b4, h4, d4, a4, e4, f4, c4, g4},
{b5, h5, d5, a5, e5, f5, c5, g5}}


Where an element is missing I want to replace it with a zero to obtain rows of equal length. Using numbers it would look like:

  {{0.46, 0.23, 0.68, 0.07, 0.15, 0, 0, 0.88},
{0.21, 0, 0.86, 0, 0, 0, 0.99, 0},
{0, 0.63, 0, 0, 0, 0.11, 0.83, 0},
{0, 0, 0.31, 0.7, 0.88, 0, 0, 0.65},
{0.18, 0, 0.58, 0.15, 0, 0, 0.66, 0.09}}


I am currently using

 (row = #;
Map[(ordi = #; k = Flatten[Position[row, _?((ordi == #) &)]];
If[Length[k] == 0, 0, row[[k[[1]], 2]]]) & , order2]) &/@ data


Edit

The code in the original question is now working... (thanks @partial81 for trying it - and sorry for the confusion).

However, I am still interested in discovering different ways to get the result. Any alternative suggestions would be appreciated.

• If I use your data and in your approach order1 (instead of order, I get back your shown result ({{0.68,0.88,...}}). Also if I use {{{d, d1}, {g, g1},...} and order2 in your approach, I get back something like {{b1, h1, d1, a1, e1, 0, 0, g1},...}. So I would say, your solution works. Or arent this the results you want to have? Jun 25, 2013 at 6:29
• @partial81 indeed. the code seems to be working. see my edit. Jun 25, 2013 at 7:18

Another version which involves converting the data into a list of rules:

order2 /. Apply[Rule, data, {2}] /. Alternatives @@ order2 -> 0.

• Bravo. AbsoluteTiming -> 0.000134 . Many thanks! Jun 25, 2013 at 12:13

Your can do it by converting your data into a list of rules.

data =
{
{{d, 0.68}, {g, 0.88}, {h, 0.23}, {e, 0.15}, {b, 0.46}, {a, 0.07}},
{{d, 0.86}, {c, 0.99}, {b, 0.21}}, {{c, 0.83},
{h, 0.63}, {f, 0.11}}, {{d, 0.31}, {g, 0.65}, {e, 0.88},
{a, 0.70}}, {{d, 0.58}, {g, 0.09}, {c, 0.66}, {b, 0.18}, {a, 0.15}}
};

default = {#, 0.} & /@ {b, h, d, a, e, f, c, g};

rules = Map[({#[[1]], 0.} -> {#[[1]], #[[2]]}) &, data, {2}]

{{{d, 0.} -> {d, 0.68}, {g, 0.} -> {g, 0.88}, {h, 0.} -> {h, 0.23},
{e, 0.} -> {e, 0.15}, {b, 0.} -> {b, 0.46}, {a, 0.} -> {a, 0.07}},
{{d, 0.} -> {d, 0.86}, {c, 0.} -> {c, 0.99}, {b, 0.} -> {b, 0.21}},
{{c, 0.} -> {c, 0.83}, {h, 0.} -> {h, 0.63}, {f, 0.} -> {f, 0.11}},
{{d, 0.} -> {d, 0.31}, {g, 0.} -> {g, 0.65}, {e, 0.} -> {e, 0.88},
{a, 0.} -> {a, 0.7}},
{{d, 0.} -> {d, 0.58}, {g, 0.} -> {g, 0.09}, {c, 0.} -> {c, 0.66},
{b, 0.} -> {b, 0.18}, {a, 0.} -> {a, 0.15}}}

Map[Last, Table[default /. r, {r, rules}], {-2}]

{{0.46, 0.23, 0.68, 0.07, 0.15, 0., 0., 0.88},
{0.21, 0., 0.86, 0., 0., 0., 0.99, 0.},
{0., 0.63, 0., 0., 0., 0.11, 0.83, 0.},
{0., 0., 0.31, 0.7, 0.88, 0., 0., 0.65},
{0.18, 0., 0.58, 0.15, 0., 0., 0.66, 0.09}}
`
• nice answer. thanks! Jun 25, 2013 at 12:06