RE: labeling problem

*To*: mathgroup at smc.vnet.net*Subject*: [mg46452] RE: [mg46430] labeling problem*From*: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>*Date*: Thu, 19 Feb 2004 03:02:01 -0500 (EST)*Sender*: owner-wri-mathgroup at wolfram.com

>-----Original Message----- >From: Janos [mailto:janos.lobb at yale.edu] To: mathgroup at smc.vnet.net >Sent: Wednesday, February 18, 2004 6:37 AM >To: mathgroup at smc.vnet.net >Subject: [mg46452] [mg46430] labeling problem > > >Before I re-invent the wheel let me ask: > >I need to assign names to list elements in a nested list based upon >their position in the nested list. For example if I have a list: > >lst = {{a,b},{c,d},e,f,{g,h,i},j,k,{l.m},{n,o,p},q,{r,s},{{t}}} > >then >pos=Position[lst,{_,_,_}] will give me > >{{5}.{9}} > >Now, I am thinking to assign a unique name to the list elements on >these positions, like p5={g,h,i} and p9={n,o,p}. I did not find yet >how to create variable names with concatenation auto-magically from >program. In other programming languages I can do something like this: > >var="p"+NumToString[5] >&var={a,b,c} > >and I could refer to it afterward as p5 and its value would be >{a,b,c}. > The most handy would be if I could take just the name of the >position >and assign that to it, like: >For[i=1, i<=Length[pos], i++, NumberToName[pos[[i]]]=lst[[pos[[i]] ]] ] > >and I would get: > >five={g,h,i} and nine={n,o,p}. > >Of course lst[[pos[[i]] ]] where' i' goes from 1 to 2 is >somewhat doing >it but it is a little bit complicated. > >I looked the book and the online documentation but could not find a >function called NumberToName which would do > >NumberToName[5] >five > >and vice versa > >NameToNumber[five] >5 > >Is there such function or procedure in someone's drawer ? >If not, then what is the right way to get a unique variable name with >some clear deterministic nature - like above - from Mathematica ? > >Thanks ahead, >János > >------------------------------------------ >"There was a mighty king in the land of the Huns whose goodness and >wisdom had no equal." >Nibelungen-Lied > Etzel, for referential integrity, I normally would not intend to do such things, and just use Part; but certainly you will have your reasons. Here is a way to do it (among others), and showing possible pitfalls: In[1]:= lst = {{a, b}, {c, d}, e, f, {g, h, i}, j, k, {l.m}, {n, o, p}, q, {r, s}, {{t}}}; This constructs a row of symbols you wanted: In[2]:= ss = Symbol /@ ("p" <> ToString[#] &) /@ Range[Length[lst]] Out[2]= {p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12} We may assign them easily at one go: In[3]:= Evaluate[ss] = lst; The p's have been assigned, e.g. In[4]:= {p5, p9} Out[4]= {{g, h, i}, {n, o, p}} So far so good; but we cannot repeat the trick: In[5]:= lst2 = {{a, {b, c}, d}, e, f, g, {h, i, j}, k, l, {m, n}, {o, p}, q, r, {s}, {{t}}}; In[6]:= ss2 = Symbol /@ ("p" <> ToString[#] &) /@ Range[Length[lst2]] Out[6]= {{a, b}, {c, d}, e, f, {g, h, i}, j, k, {l.m}, {n, o, p}, q, {r, s}, {{t}}, p13} As now the p's have values, ss2 gets these values, except for the newly generated ones, and such ss2 cannot broker the assignment intended. Neither can ss, nor can we easily Clear them. Of course you may reassign the single symbols p5 = lst2[[5]] or, if you like to type a lot {p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13} = lst2; In principle we may get at the Symbols as they still are there at the OwnValues of ss, and reassign (or Clear) them, e.g. In[11]:= MapThread[Set, {Thread[Extract[OwnValues[ss], {1, 2}, Unevaluated]], Take[{{a, {b, c}, d}, e, f, g, {h, i, j}, k, l, {m, n}, {o, p}, q, r, {s}, {{t}}}, Length[ss]]}] Out[11]= {{a, {b, c}, d}, e, f, g, {h, i, j}, k, l, {m, n}, {o, p}, q, r, {s}} In[14]:= {p5, p9} Out[14]= {{h, i, j}, {o, p}} ...but, as you see, that's not quite such simple. An easier way would be to store in ss the Unevaluated symbols: In[15]:= Quit[] In[1]:= ss = Unevaluated /@ Symbol /@ ("p" <> ToString[#] &) /@ Range[25] In[3]:= lst = {{a, b}, {c, d}, e, f, {g, h, i}, j, k, {l.m}, {n, o, p}, q, {r, s}, {{t}}}; Now to assign them: In[5]:= MapThread[Set, {Take[ss, Length[lst]], lst}] In[6]:= {p5, p9} Out[6]= {{g, h, i}, {n, o, p}} Or inspect them all: In[7]:= Evaluate /@ ss Out[7]= {{a, b}, {c, d}, e, f, {g, h, i}, j, k, {l.m}, {n, o, p}, q, {r, s}, {{t}}, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25} Clear or Unset them (befor reuse): In[12]:= Unset /@ ss; In[13]:= Evaluate /@ ss Out[13]= {p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25} Your NumberToName function is now an exercise -- I leave to you -- if you first define a function NumberName which generates the strings, and then make the symbols: In[24]:= ss = Unevaluated /@ Symbol /@ NumberName /@ Range[25] In[26]:= MapThread[Set, {Take[ss, Length[lst]], lst}]; In[27]:= {five, nine} Out[27]= {{g, h, i}, {n, o, p}} In[29]:= Clear /@ ss -- Hartmut Wolf