0

I have a unique double corresponding to a variation of three strings. I want to populate a dictionary or something such that I can call something like dict[key1][key2][key3] and get the value.

I've tried a whole bunch of things like

    Dictionary<string, Dictionary<string, double>> dict = new Dictionary<string, Dictionary<string, double>> {
        { "Foo", {"Bar", 1.2 } },
        { "Foo", {"Test", 3.4 } }
    };

Which gives me syntax errors and errors like "Error 4 A namespace cannot directly contain members such as fields or methods"

And

    Dictionary<double, Tuple<string, string>> dict = {
          {1.23, "Blah", "Foo"}
    };

Which gives me errors like "Error 1 Can only use array initializer expressions to assign to array types. Try using a new expression instead."

And

    object dict = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();

    dict["k1"] = new Dictionary<string, Dictionary<string, string>>();
    dict["k1"]["k2"] = new Dictionary<string, string>();
    dict["k1"]["k2"]["k3"] = 3.5;

Which gives me syntax errors and errors like "Error 2 Invalid token '"k1"' in class, struct, or interface member declaration"

How should I go about this? Thanks in advance.

![enter image description here][1]

enter image description here

Edit: Trying Jonesy's code:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        string[] grades = { "Grade 1", "Grade 5", "Grade 8", "ASTM A325", "316 Stainless", "Monel", "Brighton Best 1960" };
        string[] sizes = { "#1", "2", "3", "4", "5", "6", "8", "10", "12", "1/4", "5/16", "3/8", "7/16", "1/2", "9/16", "5/8", "3/4", "7/8", "1", "1-1/8", "1-1/4", "1-3/8", "1-1/2" };

        var dict = new Dictionary<string, Dictionary<string, Dictionary<string, double>>>();
        dict["k1"] = new Dictionary<string, Dictionary<string, double>>();
        dict["k1"]["k2"] = new Dictionary<string, double>();
        dict["k1"]["k2"]["k3"] = 3.5;


        public Form1()
        {
            InitializeComponent();
        } 
Charles Clayton
  • 17,005
  • 11
  • 87
  • 120
  • 1
    Please explain *how* it is not working. It's very difficult to address the problem you're encountering if you tell us nothing about it. – tnw Jan 06 '15 at 19:17
  • Thanks for your update, but the code you are showing does not demonstrate the error message you're claiming. – tnw Jan 06 '15 at 19:23
  • Visual Studios gives me errors when I use var like `Error The contextual keyword 'var' may only appear within a local variable declaration` That one also isn't ideal because I have many values to input and I don't want to use three lines for every value. – Charles Clayton Jan 06 '15 at 19:24
  • Again, the code you're showing does not demonstrate that problem. Please show the actual code that is generating the errors you claim. – tnw Jan 06 '15 at 19:25
  • Seriously? don't you find any other datastructure? omg, three level nested dictionaries? That's a mess. Please consider redesigning your code to use better datastructure. – Sriram Sakthivel Jan 06 '15 at 19:26
  • Yes, it does. I'm using Visual Studios 2012 Express, and if I use Jonesy's code below it gives me 27 errors, mostly to do with `Invalid tokens in class, struct, or interface members` like [, k1, ( etc. and all sorts of stuff to do with `namepsace ?Attribute could not be found` – Charles Clayton Jan 06 '15 at 19:28
  • @Sriram Sakthivel That's why I asked how I should go about this... I'm very open to better suggestions. – Charles Clayton Jan 06 '15 at 19:29
  • You didn't said what is the problem you're trying to solve. What will you put in those three level dictionaries? What do they represents? – Sriram Sakthivel Jan 06 '15 at 19:31
  • I need to map three strings to a double. It's not really relevant, but they keys are bolt size, bolt thread, and metal grade, and they correspond to hardcoded values for torque coefficients. – Charles Clayton Jan 06 '15 at 19:34
  • If they are hardcoded values, why do you need a dictionary? Can't they be just constants? – Sriram Sakthivel Jan 06 '15 at 19:46
  • There are like 5000 of them. The user inputs the size, thread, and grade and I need to get the torque coefficient and then get other stuff. How would you declare them as just constants that you could look up? – Charles Clayton Jan 06 '15 at 19:48

2 Answers2

5

your last attempt is close, you want:

var dict = new Dictionary<string, Dictionary<string, Dictionary<string, double>>>();
dict["k1"] = new Dictionary<string, Dictionary<string, double>>();
dict["k1"]["k2"] = new Dictionary<string, double>();
dict["k1"]["k2"]["k3"] = 3.5;

you want var instead of object

(or Dictionary<string, Dictionary<string, Dictionary<string, double>>> if you like scrolling)

and your very last string should be a double.

Jonesopolis
  • 25,034
  • 12
  • 68
  • 112
  • This code gives me a whole list of errors like `Error 1 Invalid token '[' in class, struct, or interface member declaration` `Error 14 Invalid token '"k1"' in class, struct, or interface member declaration`, and `Identifier expected`. – Charles Clayton Jan 06 '15 at 19:32
  • 1
    You're using the code outside of a method. Put it in a function. – Jonesopolis Jan 06 '15 at 19:38
0

As I understood, you have data and want to perform lookup in it. Why can't you just use some database for that purpose?

But if you really want to hardcode all values, you can. Just don't initialize dictionary manually, make simplifications - parse data in runtime.

Something like this. (I suppose, that you are novice in c# programming, so I've created new Console Application and copy-pasted all the code for your convenience)

public class Program
{
    // harcode all data as string
    const string RawData =
        "k11,k12,k13=3.4;" +
        "k21,k22,k23=4.42;" +
        "k31,k32,k33=5.91;" +
        "k41,k42,k43=8.14;" +
        "k51,k52,k53=4.13;" +
        "k61,k62,k63=5.4";

    static void Main(string[] args)
    {
        // create dictionary from hardcoded string
        var data = ParseData();

        // use Tuple as key for data lookup
        var value = data[Tuple.Create("k11", "k12", "k13")];

        // check, that value equals expected one
        Debug.Assert(value == 3.4);
    }

    private static IDictionary<Tuple<string, string, string>, double> ParseData()
    {
        var parsedData =
            RawData
                .Split(';')
                .Select(ParseRow)
                .ToDictionary(x => x.Item1, x => x.Item2);

        return parsedData;
    }

    private static Tuple<Tuple<string, string, string>, double> ParseRow(string row)
    {
        var parts = row.Split('=');
        var coefficients = ParseCoefficients(parts[0]);
        var value = Double.Parse(parts[1], CultureInfo.InvariantCulture);

        return Tuple.Create(coefficients, value);
    }

    private static Tuple<string, string, string> ParseCoefficients(string row)
    {
        var coeffs = row.Split(',');
        var result = Tuple.Create(coeffs[0], coeffs[1], coeffs[2]);

        return result;
    }
}

As another simplification, you can use custom class as dictionary key instead of nested dictionaries. Write your own(pay attention, that it should override equality members Equals and GetHashCode), or use something from base class library. Tuple<string, string, string> is the perfect one.

Uladzislaŭ
  • 1,680
  • 10
  • 13