Re: associative arrays
- To: mathgroup at smc.vnet.net
- Subject: [mg63907] Re: associative arrays
- From: Peter Pein <petsie at dordos.net>
- Date: Sat, 21 Jan 2006 01:51:03 -0500 (EST)
- References: <dqn7t9$l8m$1@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
ekantian schrieb:
> ok, i know from this group that to see keys in a hash (as in per keys
> %hash) in would use
>
> keys[hash_] := Map[#[[1, 1, 1]] &, DownValues[hash]];
>
> however, what if i have multiple levels of keys, like
>
> a[levelone][leveltwo]={1,2,3}
> a[levelone][level2]={4,5,6}
> a[levelA][levelB]={7,8,9}
>
> I need keys[a] to give me {levelone, levelA} and keys[a[levelone]] to
> give me {leveltwo, level2}, etc.
>
> Any ideas? Please post. Thx.
>
Hi ekantian,
here is a function with varying depth:
Off[General::spell1];
a[levelone][leveltwo] = {1, 2, 3};
a[levelone][level2] = {4, 5, 6};
a[levelA][levelB][levelC] = {7, 8, 9};
FullForm[SubValues[a]]
Out[5]//FullForm=
{HoldPattern[a[levelone][level2]] :> {4, 5, 6},
HoldPattern[a[levelone][leveltwo]] :> {1, 2, 3},
HoldPattern[a[levelA][levelB][levelC]] :> {7, 8, 9}}
It's easier (imho) to manipulate a simple list than this list of rules:
keylist[b_Symbol] :=
Cases[SubValues[b], Verbatim[HoldPattern][(f_)[k_]] :>
Flatten[{f //. g_[j_] :> {g, j}, k}], Infinity];
keylist[a]
Out[7]=
{{a, levelone, level2}, {a, levelone, leveltwo}, {a, levelA, levelB, levelC}}
The function keys[] has to decide whether it gets the name of the function or one of the keys:
keys[k1_Symbol, b_Symbol:(*put the name of your hash function here:*)a] :=
Module[{ls = keylist[k1]},
If[ls == {},
ls = keylist[b];
Simplify[Cases[ls, kl:{b, ___, k1, k___} :>
If[{k} == {}, Fold[#1[#2] & , b, Rest[kl]],
First[{k}]], 1]],
(*else*)Union[ls[[All,2]]]]];
keys[a]
--> {levelA, levelone}
keys[levelone]
--> {level2, leveltwo}
keys[levelB]
--> {levelC}
keys[leveltwo]
--> {{1, 2, 3}}
keys[levelC]
--> {{7, 8, 9}}
hth,
Peter