Hashtable with multiple values for single key
Asked Answered
B

11

14

I want to store multiple values in single key like:

HashTable obj = new HashTable();
obj.Add("1", "test");
obj.Add("1", "Test1");

Right now this throws an error.

Bole answered 29/12, 2010 at 13:24 Comment(3)
If keys are numbers use int as key, not string, if applicable.Orgell
This question is a duplicate of stackoverflow.com/questions/2478567 and stackoverflow.com/questions/4454075Dactylology
Possible duplicate of What is the best .NET type for collections where each key can have multiple values?Serpigo
S
9

you can put your test,test1,test2,... in a table and then put this table in a Hashtable as a value for the key which will be the same for all them.

For example try something like this:

List<string> list = new List<string>();
list.Add("test");
list.Add("test1"); 

and then:

HashTable obj = new HashTable();
obj.Add("1", list);
Sexdecillion answered 29/12, 2010 at 13:47 Comment(0)
B
6

You can't use the same key in a Dictionary/Hashtable. I think you want to use a List for every key, for example (VB.NET):

Dim dic As New Dictionary(Of String, List(Of String))
Dim myValues As New List(Of String)
myValues.Add("test")
myValues.Add("Test1")
dic.Add("1", myValues)

C#:

Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>();
List<string> myValues = new List<string>();
myValues.Add("test");
myValues.Add("Test1");
dic.Add("1", myValues);
Bartel answered 29/12, 2010 at 13:29 Comment(0)
A
5

I'm using my own MultiDictionary class. It's based on a Dictionary<TKey,List<TValue>> but offers a bit of syntax sugar on top of that. Should be easy to extent Entry<TValue> to implement IList<T>

public class MultiDictionary<TKey, TValue>
{
    private Dictionary<TKey, List<TValue>> data = new Dictionary<TKey, List<TValue>>();

    public struct Entry : IEnumerable<TValue>
    {
        private readonly MultiDictionary<TKey, TValue> mDictionary;
        private readonly TKey mKey;

        public TKey Key { get { return mKey; } }

        public bool IsEmpty
        {
            get
            {
                return !mDictionary.data.ContainsKey(Key);
            }
        }

        public void Add(TValue value)
        {
            List<TValue> list;
            if (!mDictionary.data.TryGetValue(Key, out list))
                list = new List<TValue>();
            list.Add(value);
            mDictionary.data[Key] = list;
        }

        public bool Remove(TValue value)
        {
            List<TValue> list;
            if (!mDictionary.data.TryGetValue(Key, out list))
                return false;
            bool result = list.Remove(value);
            if (list.Count == 0)
                mDictionary.data.Remove(Key);
            return result;
        }

        public void Clear()
        {
            mDictionary.data.Remove(Key);
        }

        internal Entry(MultiDictionary<TKey, TValue> dictionary, TKey key)
        {
            mDictionary = dictionary;
            mKey = key;
        }

        public IEnumerator<TValue> GetEnumerator()
        {
            List<TValue> list;
            if (!mDictionary.data.TryGetValue(Key, out list))
                return Enumerable.Empty<TValue>().GetEnumerator();
            else
                return list.GetEnumerator();
        }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

    public Entry this[TKey key]
    {
        get
        {
            return new Entry(this, key);
        }
    }
}
Antiphon answered 29/12, 2010 at 13:45 Comment(0)
F
1

You could use a dictionary.

Actually, what you've just described is an ideal use for the Dictionary collection. It's supposed to contain key:value pairs, regardless of the type of value. By making the value its own class, you'll be able to extend it easily in the future, should the need arise.

Sample code:

class MappedValue
{
    public string SomeString { get; set; }
    public bool SomeBool { get; set; }
}

Dictionary<string, MappedValue> myList = new Dictionary<string, MappedValue>;
Fermium answered 29/12, 2010 at 13:26 Comment(1)
If OP can use .NET 4.0 then he can also use just Tuble<string, bool>, etc.Orgell
E
1

That throws an error because you're adding the same key twice. Try using a Dictionary instead of a HashTable.

Dictionary<int, IList<string>> values = new Dictionary<int, IList<string>>();
IList<string> list = new List<string>()
{
    "test", "Test1"
};
values.Add(1, list);
Ermaermanno answered 29/12, 2010 at 13:27 Comment(2)
IList is for dynamic storing + getting by index. For just dynamic storing is `ICollection<string>, isn't it?Orgell
Sure, depends what he wants, he could use IEnumerable, ICollection, IList, string[]... whatever he needsErmaermanno
M
1

You're looking for a Lookup, which can natively store multiple values for each key.

As pointed out this only works for a fixed list since you cannot add entries to a lookup once you have created it.

public class LookupEntry
{
    public string Key { get; set; }
    public string Value { get; set; }
}

var list = new List<LookupEntry>(new LookupEntry [] 
                                    {
                                    new LookupEntry() {Key="1", Value="Car" }, 
                                    new LookupEntry() {Key="1", Value="Truck"},
                                    new LookupEntry() {Key="2", Value="Duck"}
                                    });


var lookup = list.ToLookup(x => x.Key, x => x.Value);
var all1s = lookup["1"].ToList();
Meanie answered 29/12, 2010 at 13:35 Comment(1)
Lookup is immutable. That can be nice, but might not work in the OPs scenario.Antiphon
C
1

Probably it is 4 years later, but I hope it will help somebody later. As mentioned earlier in the post, it is not possible to use the same key for different values in Hashtable(key, value). Although, you may create a List or some object as a value in the key/value pair of HashTable.

//instantiate new Hashtable
Hashtable hashtable = new Hashtable();

//create a class that would represent a value in the HashTable
public class SomeObject
{
    public string value1 { get; set;}
    public string value2 { get; set;}
}

//create a List that would store our objects
List<SomeObject> list = new List<someObject>();

//add new items to the created list
list.Add(new SomeObject() 
             { 
                 value1 = "test", 
                 value2 = "test1"
             });
list.Add(new SomeObject() 
             {
                 value1 = "secondObject_value1" 
                 value2 = "secondObject_value2"
             })

//add key/value pairs to the Hashtable.
hashTable.Add("1", list[0]);
hashTable.Add("2", list[1]);

Then to retrieve this data:

//retrieve the value for the key "1"
SomeObject firstObj = (SomeObject)hashTable[1];
//retrieve the value for the key "2"
SomeObject secondObj = (SomeObject)hashTable[2];
Console.WriteLine("Values of the first object are: {0} and {1}", 
                                             firstObj.value1,firstObj.value2);
Console.WriteLine("Values of the second object are {0} and {1}",
                                             secondObj.value1, secondObj.value2);
// output for the WriteLine:
Values of the first object are: test and test1
Values of the second object are secondObject_value1 and secondObject_value2
Chemurgy answered 8/8, 2014 at 8:45 Comment(0)
H
0

Store a list in the hashtable:

obj.Add("1",new List<string>());
(obj["1"] as List<string>).Add("test");
(obj["1"] as List<string>).Add("test1");

This is a common trick.

Herculean answered 29/12, 2010 at 13:26 Comment(1)
If you're sure in the resulting type then use cast, not operator as. And anyway - use generic collection, not .NET 1.x non-generic one.Orgell
O
0

JFYI, you can declare your dic this way:

Dictionary<int, IList<string>> dic = new
{
    { 1, new List<string> { "Test1", "test1" },
    { 2, new List<string> { "Test2", "test2" }
};
Orgell answered 29/12, 2010 at 13:46 Comment(0)
O
0

You can use NameValueCollection - works the same as hashtable and has the "GetValues()".

Outgroup answered 13/6, 2013 at 11:2 Comment(0)
A
0

It would be better for you to use two hashtables as I've used in this library

Alethiaaletta answered 20/9, 2013 at 2:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.