In his answer to this question, Leonid helped me find a way to programmatically generate contexts for holding sets of symbols with the same names. Perhaps a simpler way is to use DownValues so:

dataRaw["Paris"] = Import["Paris.csv"];
data["Paris"] = Differences[dataRaw["Paris"]];
dataMax["Paris"] = Max[dataRaw["Paris"]];

dataRaw["Madrid"] = Import["Madrid.csv"];
data["Madrid"] = Differences[dataRaw["Madrid"]];
dataMax["Madrid"] = Max[dataRaw["Madrid"]];

lets me make a plot using

ListLinePlot[data /@ {"Paris", "Madrid"}]

and can be implemented with a simple function

importCity[cityName_String] := (
    dataRaw[cityName] = Import[cityName ~~ ".csv"];
    data[cityName] = Differences[dataRaw[cityName]];
    dataMax[cityName] = Max[dataRaw[cityName]];

Other than cluttering everything with a lot of [cityName], are there hidden perils to using DownValues in this way? Is there some disadvantage to storing every dataRaw as DownValues of the same symbol instead of individually in multiple contexts?

  • 1
    $\begingroup$ Why use "paris" and ToLowerCase rather than simply "Paris"? $\endgroup$ – Mr.Wizard Mar 15 '12 at 18:22
  • $\begingroup$ Good question. That's a holdover from the context method, where (I guess) it's not a good idea to have capitalized context names. I'll update the example. $\endgroup$ – ArgentoSapiens Mar 15 '12 at 19:15
  • $\begingroup$ Actually, in a user context you are free and clear to use capitalized symbol names because there will be no collisions. $\endgroup$ – Mr.Wizard Mar 15 '12 at 19:21

Since no other answer has been posted yet I'll give my opinion.

Using DownValues, which I believe is a hash table of sorts, is the normal and accepted way to store this kind of information in Mathematica, to the best of my knowledge. I cannot think of any real disadvantages compared to direct symbol assignment.

Either form (direct assignment or DownValues) may take up considerably more memory than storing the information in large array, packed or sparse if possible. The nature of the data and how it is accessed best determine which method to use.

The other option you should be aware of is to use replacement rules. When optimized using Dispatch this will be similar to DownValues in many ways, but it allows different usages and has strengths that can make it superior in some applications.

data = Dispatch @ {"Madrid" -> 7, "Paris" -> 2, "Porto" -> 4, "Perth" -> 1};

{"Madrid", "Paris"} /. data
{7, 2}

By the way you can write importCity like this:

importCity[cityName_String] :=
  With[{raw = Import[cityName ~~ ".csv"]},
    dataRaw[cityName] = raw;
    data[cityName]    = Differences @ raw;
    dataMax[cityName] = Max @ raw;
| improve this answer | |

I use this way of storing data extensively for what I do. I collected in my answer here https://mathematica.stackexchange.com/a/999/66 several ideas I developed over time around this type of structure. The Keys function based on what dreeves once submitted on StackOverflow ( https://stackoverflow.com/a/154704/884752 ) is what makes this structure practical as you can see all the indices of a symbol used to index its values.

I was lucky to have found this data structure as I began learning Mathematica because it allowed me to do things I couldn't have done without it.

SetAttributes[RemoveHead, {HoldAll}];
RemoveHead[h_[args___]] := {args};
NKeys[_[symbol_Symbol]]:=NKeys[symbol]; (*for the head[object] case*)
NKeys[symbol_] := RemoveHead @@@ DownValues[symbol(*,Sort->False*)][[All,1]];
Keys[symbol_] := Replace[NKeys[symbol], {x_} :> x, {1}];

| improve this answer | |
  • $\begingroup$ This reminds me "dict" in python. Good way to get all the keys quickly. $\endgroup$ – FJRA Mar 16 '12 at 23:39

In contrast to symbols, part replacement with downvalues requires use of a temporary variable, (unless there is a better way). E.g.

enter image description here

| improve this answer | |
  • $\begingroup$ I momentarily voted for this, but I am not sure how this relates to the comparison of symbols to DownValues. Do you mean an array? $\endgroup$ – Mr.Wizard Mar 17 '12 at 13:59
  • $\begingroup$ @ Mr.Wizard. Yes, an array or list. If symbol a = {1, 2, 3, 4, 5} part replacement can be done, but if f[1] = {1, 2, 3, 4, 5} it is not so straightforward. $\endgroup$ – Chris Degnen Mar 17 '12 at 20:08
  • 1
    $\begingroup$ This is the main drawback of this data structure. The best solution to this is in my opinion something like f[1] = ReplacePart[f[1], 3 -> 6] $\endgroup$ – faysou Mar 17 '12 at 20:29
  • $\begingroup$ @ Faysal. More complex replacements like a[[{3, 4}]] = {1, 2} would be cumbersome to set up. Then I would use the temp variable. $\endgroup$ – Chris Degnen Mar 17 '12 at 21:09
  • $\begingroup$ Alright. +1 It might be an interesting question to ask what cleanest method to effect that operation is. $\endgroup$ – Mr.Wizard Mar 17 '12 at 22:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.