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.

Let there be a sample list as ,

l = {a, {{b, c}}, {d, e}, {f}, {{g, {y}, u, h}, {{{{k, j}}}}},k, {{{{q}, {w}, {r}, {x}}}}};
ArrayRules[l]

ArrayRules::rect: Nonrectangular array encountered. >>

is the error thrown. So, I was just wondering that if someone needs to preserve list structure using a similar kind of functionality, than what might be the steps needed. My intention is to pass data to replace later rather than as rule in ArrayRules. I could parse list to find positions information like ArrayRules using following code,

 ListRules[l_List] :=
 Module[{l1 = l, l11, s1, pos, M, tpos, trpos, sp, ntrpos, temntrpos,
    fin, fin2},
   {l11 = {#} & /@ l1,
    s1 = Map[{#, Position[l11, #]} &, l11,Infinity] /. {a_, {{s___}}} -> {s} //. {d___, {}, e___} -> {d,e},
    pos = Table[s1[[i]] //. {___, {a___List}, ___} -> a, {i, 1,Length[s1]}],
    M = Last[SortBy[pos, Length]] // Length,
    tpos = Table[If[Length[pos[[i]]] < M, PadRight[pos[[i]], M, 1], pos[[i]]], {i, 1, Length[pos]}],
    }; tpos]
 listrules= ListRules[l]

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

Than I tried to create it back to a list using following method,

CreateList[s_List] :=
 Module[{tpos = s, trpos, sp, ntrpos, temntrpos, t, x, y,
    h}, {trpos =Table[tpos[[i]] -> RandomInteger[100], {i, 1,Length[tpos]}],
    sp = SparseArray[trpos],
    ntrpos = Normal[sp],
    temntrpos = ntrpos //. {a___, {h___, 0 ..}, b___} -> {a, h, b} //. {a___, {}, b___} -> {a, b}
    }; temntrpos
   ]
CreateList[listrules]

gives,

{{{{{{76}}}}}, {{{{{82}}, {{83}}}}}, {{{{{67}}}, {{{19}}}}}, {{{{{32}}}}}, {{{{{51}}, {{22}}, {{60}}, {{1}}}, {{{{26,59}}}}}}, {{{{{12}}}}}, {{{{{6}, {78}, {34}, {72}}}}}}

It shows that it has been able to retain nesting structure but there are extra braces associated. I tried to use Dimension, Depth etc. I can get rid of nesting for single elements by associating dimension from original list with them and flattening all those with maximum dimension as 1 for Rest[sublist]. But in case of multiple nesting, I am failing. I have to keep number of braces same in both source and destination.

share|improve this question
add comment

3 Answers

If I understood correctly, what you might want is this:

Flatten @ MapIndexed[(#2 -> #1 &), l, {-1}]
{ {1} -> a, {2,1,1} -> b, {2,1,2} -> c, {3,1} -> d, {3,2} -> e,
  {4,1} -> f, {5,1,1} -> g, {5,1,2,1} -> y, {5,1,3} -> u, {5,1,4} -> h,
  {5,2,1,1,1,1} -> k, {5,2,1,1,1,2} -> j, {6} -> k, {7,1,1,1,1} -> q, 
  {7,1,1,2,1} -> w, {7,1,1,3,1} -> r, {7,1,1,4,1} -> x }

Is it right?

share|improve this answer
    
No that's not what I am looking for actually. Though thanks for suggestion, I am aware of this already. –  Rorschach Nov 9 '13 at 14:09
add comment

I interpret your question as asking how to use a given list as a template for building a tree, your goal being to produce a new tree with the same structure as the given one, but withe new leaves extracted from a second list. If my interpretation is correct, you can proceed as follows:

tree = 
  {a, {{b, c}}, {d, e}, {f}, {{g, {y}, u, h}, {{{{k, j}}}}}, k, {{{{q}, {w}, {r}, {x}}}}};
leaves = tree // Flatten;
SeedRandom[42]; data = RandomInteger[100, Length @ leaves];
rules = Thread[Rule[leaves, data]];
dataTree = tree /. rules
{54, {{66, 4}}, {15, 6}, {3}, {{95, {32}, 48, 3}, {{{{81, 87}}}}}, 81, 
 {{{{88}, {98}, {48}, {44}}}}}
share|improve this answer
    
Your interpretation is correct but this will replace elements rather than preserving list structure. It is escaping the significance of list format. –  Rorschach Nov 9 '13 at 14:20
    
@Blackbird. I don't understand your comment. My approach preserves the structure of the template list exactly. –  m_goldberg Nov 9 '13 at 15:53
    
Sorry for unclear comment,I meant to say that I want to follow the approach I am using. I need to associate some info with each sublist that decides number of braces.I hope I could make myself more clear. –  Rorschach Nov 9 '13 at 17:22
add comment

It is not clear to me exactly what you want. If user8074's method is helpful you may also consider using Position as follows which will work with non-atomic elements as well.

l = {a, {{b, c}}, {d, e}, {f}, {{g, {y}, u, h}, {{{{k, j}}}}}, 
   k, {{{{q}, {w}, {r}, {x}}}}};

pos = Position[l, Except[_List], Heads -> False]
{{1}, {2, 1, 1}, {2, 1, 2}, {3, 1}, {3, 2}, {4, 1}, {5, 1, 1}, {5, 1, 2, 1}, {5, 1, 3},
 {5, 1, 4}, {5, 2, 1, 1, 1, 1}, {5, 2, 1, 1, 1, 2}, {6}, {7, 1, 1, 1, 1}, {7, 1, 1, 2, 1},
 {7, 1, 1, 3, 1}, {7, 1, 1, 4, 1}}

You can Extract the elements using those positions:

elem = Extract[l, pos]
{a, b, c, d, e, f, g, y, u, h, k, j, k, q, w, r, x}

You can also replace the elements using ReplacePart:

new = Range[17];

ReplacePart[l, Thread[pos -> new]]
{1, {{2, 3}}, {4, 5}, {6}, {{7, {8}, 9, 10}, {{{{11, 12}}}}}, 13,
 {{{{14}, {15}, {16}, {17}}}}}

Does this help?

share|improve this answer
    
No doubt this solves the problem but I am trying to work it through Sparse array,because preserving information this way, I can use it to create sparse array or NonSparse array. My precise question is that what information I shall associate with each sublist that it will help me put right number of parenthesis. –  Rorschach Nov 9 '13 at 14:14
add comment

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.