El diccionario con varias claves no funciona como se esperaba

I'm making a console program where I've got multiple values mapped to dictionary keyLookup. I'm using if commands that use the key to output some console.writeline = ("stuff"); but it only works if I have the value and the key the same (in the dictionary). I don't know why this is. I've been mucking about with list y foreach and some variables trying to figure out what I've done wrong but even though it continues to work how it works now it still doesn't work how I want.

Also if I have a word in my console.readline(); that isn't in my dictionary the whole thing crashes. Which I don't want, and I'm not sure of why its doing that either as at some point it didn't. Also my mathFunction dictionary works just how I want my keyLookup dictionary to work. Though I think the difference is in how I'm using a list to cross reference through keyLookup.

class MainClass
        public static string Line;
        static string foundKey;
        public static void Main (string[] args)
            while (true) 
                if (Line == null)
                {Console.WriteLine ("Enter Input"); }
                WordChecker ();
    public static void WordChecker()
        string inputString = Console.ReadLine ();
        inputString = inputString.ToLower();  

        string[] stripChars = { ";", ",", ".", "-", "_", "^", "(", ")", "[", "]",
            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "\n", "\t", "\r" };

        foreach (string character in stripChars)
            inputString = inputString.Replace(character, "");
        // Split on spaces into a List of strings
        List<string> wordList = inputString.Split(' ').ToList();
        // Define and remove stopwords
        string[] stopwords = new string[] { "and", "the", "she", "for", "this", "you", "but" };

        foreach (string word in stopwords)
            // While there's still an instance of a stopword in the wordList, remove it.
            // If we don't use a while loop on this each call to Remove simply removes a single
            // instance of the stopword from our wordList, and we can't call Replace on the
            // entire string (as opposed to the individual words in the string) as it's
            // too indiscriminate (i.e. removing 'and' will turn words like 'bandage' into 'bdage'!)
            while ( wordList.Contains(word) )
        // Create a new Dictionary object
        Dictionary<string, int> dictionary = new Dictionary<string, int>();

        // Loop over all over the words in our wordList...

        foreach (string word in wordList)
            // If the length of the word is at least three letters...

            if (word.Length >= 3) 

                // ...check if the dictionary already has the word.

                if ( dictionary.ContainsKey(word) )

                    // If we already have the word in the dictionary, increment the count of how many times it appears

                    // Otherwise, if it's a new word then add it to the dictionary with an initial count of 1

                    dictionary[word] = 1;

            List<string> dicList = new List<string>();
            dicList = dictionary.Keys.ToList ();

            Dictionary<string, string> keyLookup = new Dictionary<string, string>();

            keyLookup["hey"] = "greeting";
            keyLookup["hi"] = "greeting";
            keyLookup["greeting"] = "greeting";
            keyLookup["math"] = "math";
            keyLookup["calculate"] = "math";
            keyLookup["equation"] = "math";

            foundKey = keyLookup[word];

            List<string> keyList = new List<string>();

            foreach (string keyWord in dicList)
                if(keyWord == foundKey)
                {keyList.Add (keyWord); }

            foreach (string mKey in keyList)
            if(mKey == "greeting")
            {Greetings ();}

            if (mKey == "math") 
            {Math ();}

    public static void Math()
        Console.WriteLine ("What do you want me to math?");
        Console.WriteLine ("input a number");
        string input = Console.ReadLine ();

        decimal a = Convert.ToDecimal (input);
        Console.WriteLine("Tell me math function");
        string mFunction = Console.ReadLine();

        Console.WriteLine ("tell me another number");
        string inputB = Console.ReadLine();
        decimal b = Convert.ToDecimal (inputB);

        Dictionary<string, string> mathFunction = new Dictionary<string, string>();

        mathFunction["multiply"] = "multiply";
        mathFunction["times"] = "multiply";
        mathFunction["x"] = "multiply";
        mathFunction["*"] = "multiply";
        mathFunction["divide"] = "divide";
        mathFunction["/"] = "divide";
        mathFunction["subtract"] = "subtract";
        mathFunction["minus"] = "subtract";
        mathFunction["-"] = "subtract";
        mathFunction["add"] = "add";
        mathFunction["+"] = "add";
        mathFunction["plus"] = "add";

        string foundKey = mathFunction[mFunction];

        if (foundKey == "add")
            Console.WriteLine (a + b);
        else if (foundKey == "subtract")
            Console.WriteLine (a - b);
        else if (foundKey == "multiply")
            Console.WriteLine (a * b);
        else if (foundKey == "divide")
            Console.WriteLine (a / b);
            Console.WriteLine ("not a math");

    public static void Greetings()
        Console.WriteLine("You said hello");

preguntado el 25 de mayo de 13 a las 21:05

This is a very convoluted question. What are you trying to achieve exactly? There is definitely a way to do all of this with muy muy fewer lines of code using LINQ, if you can just explain a bit more clearly what result you are looking for. -

I'm trying to make a program that I can type lines into in a 'conversational fashion' and have it grab keywords from what I say and execute functions. For example the math I have it doing now. Later on I want to try to have it do more complex things but first I need to get it reading my input properly. yeah I know it could be done in less code. I'm a total noob though :) -

I was going look into this further, but this code needs a total re-write. I found two errors and a couple places you could use predicate functions. -

2 Respuestas

You should iterate through the dictionary differently (Dont use ToList-Function).

Prueba esto en su lugar:

foreach (KeyValuePair kvp (Of String, String) In testDictionary)
  Debug.WriteLine("Key:" + kvp.Key + " Value:" + kvp.Value);

And your application is crashing if the word doesn't match, because of this code (You're not creating a new entry that way):

// Otherwise, if it's a new word then add it to the dictionary with an initial count of 1
dictionary[word] = 1;

EDIT: I was wrong about that dictionary[word] = 1 would not create a new element. It's perfectly fine like this.

contestado el 26 de mayo de 13 a las 11:05

I'll have to do some research before I try it out. I'm not familiar with KeyValuePair debug or Next yet. Thanks for the tip though. I'll definitelly do some reading and try to figure out how to implement it. - AsombrosoMrBrock

You can also use GetEnumerator and loop through it that way, if you're more familiar with this. - Fabián Bigler

dictionary[word] = 1; es correcta. msdn.microsoft.com/en-us/library/9tee9ht2.aspx . If the specified key is not found, a get operation throws a KeyNotFoundException, and **a set operation creates a new element with the specified key**. - I4V

@AmazingMrBrock this code sample is in VB.net, not C#. There's no Next keyword in C#, the equivalent C# code is foreach(var kvp in testDictionary) { Debug.WriteLine("Key: " + kvp.Key + " Value: " + kvp.Value); } - Mathieu Guindon

foundKey = keyLookup[word];

If word doesn't exist in keyLookup then it will crash.

string foundKey = mathFunction[mFunction];

if mFunction doesn't exist in mathFunction then it will crash.

If you're trying to make this a "conversational" program, then the word look-up is the most important part. You don't use predicates or LINQ, both can make string functions extremadamente easy. Currently you use a Dictionary. Why not use Lists for each keyword?

List<string> GreetingKeywords;
GreetingKeywords.Add("hello"); // ...

List<string> MathKeywords;
MathKeywords.Add("math"); // ...

foreach (var word in dicList)
  if (GreetingKeywords.Contains(word))
    { Greetings(); }
  if (MathKeywords.Contains(word))
    { Maths(); }

I'd suggest you read up on predicate and List/Dictionary functions such as Find, IndexOf, etc. etc. That knowledge is invaluable to C#.

contestado el 26 de mayo de 13 a las 03:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.