Tables often come with column headers. Indexing the columns with the header is a natural thing to do. Although a proper dictionary is the usual solution in such a case, I find it often practical and elegant to index these through the symbol corresponding to the column header string. So say: I have an array:
mtvguests = {{Last Name, First Name},{Kolmogorov, Andrei},{Milankovic, Milutin}}
mtvguests[[All, lastName]]
is a fairly natural and readable syntax.
The following two functions help towards this end:
SetAttributes[SymbolValidWMMA, Listable];
Options[SymbolValidWMMA] := {camelCase -> False, RulesStringPatterns->{"/"->"or"}}
SymbolValidWMMA[s_String, OptionsPattern[]] :=
Fold[StringReplace[#1, #2] &, s,
Join[ OptionValue[RulesStringPatterns], If[OptionValue[camelCase], {Except[WordCharacter] ~~ x_ :> ToUpperCase[x],
StartOfString ~~ Whitespace ... ~~ x_ :>
ToLowerCase[x]}, {}], {Whitespace -> "",
StartOfString ~~ x:DigitCharacter :> "d"<>x,
Except[WordCharacter] -> "" }]];
(I am not a big fan of camel case but in this case it comes as handy).
Options[IndicesFromStrings] :=
Join[Options[SymbolValidWMMA], {Prfx -> "", Sfx -> "",
Ctxt -> ""}];
IndicesFromStrings[ls_List, opts : OptionsPattern[]] :=
(ToExpression[#1 <> "=" <> ToString[First@#2]]) &
~MapIndexed~ (If[OptionValue[Ctxt] != "", OptionValue[Ctxt] <> "`",
""] <> OptionValue[Prfx] <>
SymbolValidWMMA[#,
Sequence @@ FilterRules[{opts}, Options[SymbolValidWMMA]]] <>
OptionValue[Sfx] & /@ ls);
An example.
mtvguests = {{"Kolmogorov", "Andrei"}, {"Milankovic", "Milutin"}};
Prepend[mtvguests, {"Last Name", "First Name"} ] // TableForm
Then
IndicesFromStrings[{"Last Name", "First Name", "Cycles/Operators",
"2_2_Tu"}, camelCase -> True]
yields:
{"lastName", "firstName", "cyclesorOperators", "d22Tu"}
And
mtvguests[[All, lastName]]
would return:
{"Kolmogorov", "Milankovic"}
The symbol mangling can be tweaked:
IndicesFromStrings[{"Last Name", "First Name", "Cycles/Operators",
"_2_Tu"}, Ctxt -> "mtv", camelCase -> False,
RulesStringPatterns -> {DigitCharacter -> "nb", "/" -> "",
"_" -> "U"}]
would now return:
{"mtv`LastName", "mtv`FirstName", "mtv`CyclesOperators", "mtv`UnbUTu"}
The previous works. Now for the question: I am not sure how to make the following work:
IndicesFromStrings[ls_List, opts : OptionsPattern[]] :=
(Set[ReleaseHold[ToExpression[#1]], ToString[First@#2]]) &
~MapIndexed~(If[OptionValue[Ctxt] != "", OptionValue[Ctxt] <> "`",
""] <> OptionValue[Prfx] <>
SymbolValidWMMA[#,
Sequence @@ FilterRules[{opts}, Options[SymbolValidWMMA]]] <>
OptionValue[Sfx] & /@ ls);
Set[]
, then post a minimal example. The rest of the code (notwithstanding how clever it could be) is just impedance to understand the question. $\endgroup$NAME=1;DATE=2;
. then for matrix saym={{"joe doe","1/1/2001"},{"joe doe 2","1/1/2002"}}
, I would writem[[All,NAME]]
andm[[2,DATE]]
and so on. it works and was easy to handle. Not as nice as dictionary ofcourse. Just had to remember to make sure the names of columns and the index matched what I wanted. $\endgroup$