tags:

views:

425

answers:

7

I doubt this is possible, but I was curious if you could have more than 2 items (key,value) in a dictionary. Maybe a key and 2 values. Is there a collection object that does allow this? What I am actually trying to do is to store a key and a value for the key and another value to hold the count of how many times the key has been found. For example, I may have a for loop that goes through a list of colors and each color has a unique value. As I go through the list, I not only want to store the color, the unique value of the color in a dictionary, but also store how many times red occurred in the list.

I put in the following declaration and now I am tyring to figure out how I can test to see if it contains the value already and if it does not, add it to the list with a count of 1 and if it does, increment the count. After I post the declaration, I will post how I was doing it with just one dictionary.

Dictionary<string, Dictionary<int,int>> colors = 
                          new Dictionary<string, Dictionary<int,int>>();

Here is code of how I was handling it before:

Dictionary<string, int> colors = new Dictionary<string, int>();

 foreach (Color color in ColorList)
        {
            if (colors.ContainsKey(color.ToString()))
                colors[color]++;
            else
                colors.Add(color, 1);
        }
+4  A: 

Could you perhaps have a dictionary of a struct that would keep track of the color and the number of times it occurred?

Edit: As suggested elsewhere, this could also be accomplished by building your own small custom class. Would essentially work in the same fashion.

TheTXI
You mean something like Dictionary<string, array[2]>;
Xaisoft
I suppose that's another method of doing it.
TheTXI
+3  A: 

you can use two dictionaries for this or simply create a data class that has both the color and the count and store the intermediate class instances in a dictionary.

Pop Catalin
I thought about this. I curious about tuples now though.
Xaisoft
Tuples will only save you some typing as of now (the intermediate class), unless you have a functional library that can work with them.
Pop Catalin
A: 

You're looking for a MultiMap.

I wrote the following (not fully tested):

 using System.Collections.Generic;

public class MultiMapSet<TKey, TValue>
{
    private readonly Dictionary<TKey, HashSet<TValue>> _ht = new Dictionary<TKey, HashSet<TValue>>();

    public void Add(TKey key, TValue value)
    {
        HashSet<TValue> valueSet;
        if (_ht.TryGetValue(key, out valueSet))
        {
            valueSet.Add(value);
        }
        else
        {
            valueSet = new HashSet<TValue> { value };
            _ht.Add(key, valueSet);
        }
    }

    public bool HasValue(TKey key, TValue value)
    {
        HashSet<TValue> valueSet;
        if (_ht.TryGetValue(key, out valueSet))
        {
            return valueSet.Contains(value);
        }
        return false;
    }

    public HashSet<TValue> GetValues(TKey key)
    {
        HashSet<TValue> valueSet;
        _ht.TryGetValue(key, out valueSet);
        return valueSet;
    }

    public void Remove(TKey key, TValue value)
    {
        HashSet<TValue> valueSet;
        if (!_ht.TryGetValue(key, out valueSet))
        {
            return;
        }

        if (valueSet.Contains(value))
        {
            valueSet.Remove(value);
        }
    }
}
Brent Miller
-1, while this does solve the question, it really is the wrong approach. Especially when it comes to maintaining the code.
Samuel
@Samuel: Why is this the "wrong approach"? You should back up a comment like that with reasons beyond code maintenance - what is it about this solution that makes the maintenance difficult?
Scott Dorman
I guess it's because you're defining an entire new collection when, to the best of our knowledge, the OP has a very specific use case in 1 part of his code.
Outlaw Programmer
His code actually doesn't satisfy the question. In the question there are two value types needed. It's a maintenance and readability nightmare.
Samuel
+1  A: 

Well, one way would be to have:

Dictionary<key, KeyValuePair<value, int>>

If I'm understanding your question.


Edit:

Actually, if the color and value were consistent - meaning that 'red' was always 3 or 19 or whatever you used as the value of red, then the name 'red' and the value, say 19, is really just a compound key and so you could do something like this:

Dictionary<KeyValuePair<string, int>, int> mydict;

and then for updates do something like this:

mydict[key] = mydict[key] + 1;
itsmatt
That looks right. Can you give a code example of how I would loop through that and increment the count and check for duplicates?
Xaisoft
Yes, red and the value of red are constant, the only thing that would change is the count.
Xaisoft
+2  A: 

You could make a simple Tuple class, such as a Triple. It's essentially a generically keyed dictionary but holds an additional object. It's pretty common for this scenario, people have made libraries that extend it out for 4 to 10 objects. Here's an example:

    public struct Triple<X, Y, Z>
    {
        public X First;     
        public Y Second;    
        public Z Third;     

        public Triple(X x, Y y, Z z)
        {
            First = x;
            Second = y;
            Third = z;
        }
    }

And then use it like so:

 var myTriple =  new Triple<string, Color, int>(
                        "key", 
                        myColor, 
                        count
                    )

,

womp
A: 

could you do something like

Dictonary<string,string> dh = new dictonary<string,string>();

dh.add("x","Something:0");


foreach keyvaluepair kvp in dh
{

    if kvp.key == x
    {
        string[] hold= kvp.value.split(':');
        //to update it the count it would be something like

        int y = convert.toint(hold[1])+1;
        kvp.value=hold[0]+":"+y.tostring();

     }

}
Crash893
-1: Never write code like this in production. It throws away type safety, its ridiculously inefficient, and the code is unreadable.
Juliet
+1 from me. As long as the encoding/decoding is done in the same spot, this isn't the craziest idea I've ever seen. This is a valid alternative, though I wouldn't necessarily use it.
Outlaw Programmer
A: 

Most of these answers all say pretty much the same (correct) thing. Just make the value of your 'outer' dictionary some sort of object you find most useful to doing what you need with. Personally without thinking about it I'd have gone with a dictionary of dictionary.

Dictionary<key1, Dictionary<key2, value>>
Jeff Keslinke
First thing that crossed my mind as well. Can you provide a code example of incrementing the count in the second dictionary?
Xaisoft
This really doesn't work that well, it only partially solves the question. How do you go about storing a strongly typed Color and Int32 into this dictionary?
Samuel