【问题标题】:Hashtable with multiple values for single key具有单个键的多个值的哈希表
【发布时间】:2011-06-01 01:35:28
【问题描述】:

我想在单个键中存储多个值,例如:

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

现在这会引发错误。

【问题讨论】:

标签: c# hashtable multiple-value


【解决方案1】:

您可以将您的test,test1,test2,... 放入一个表中,然后将该表放入一个哈希表中作为键的值,这对所有键都是相同的。

例如尝试这样的事情:

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

然后:

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

【讨论】:

    【解决方案2】:

    您不能在字典/哈希表中使用相同的键。 我认为您想为每个键使用一个列表,例如(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);
    

    【讨论】:

      【解决方案3】:

      我正在使用我自己的 MultiDictionary 课程。它基于Dictionary&lt;TKey,List&lt;TValue&gt;&gt;,但在此之上提供了一些语法糖。应该很容易扩展Entry&lt;TValue&gt;实现IList&lt;T&gt;

      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);
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        你可以使用字典。

        实际上,您刚才描述的是 Dictionary 集合的理想用途。无论值的类型如何,它都应该包含键:值对。通过将值设为自己的类,您可以在将来需要时轻松扩展它。

        示例代码:

        class MappedValue
        {
            public string SomeString { get; set; }
            public bool SomeBool { get; set; }
        }
        
        Dictionary<string, MappedValue> myList = new Dictionary<string, MappedValue>;
        

        【讨论】:

        • 如果 OP 可以使用 .NET 4.0,那么他也可以只使用 Tuble&lt;string, bool&gt; 等。
        【解决方案5】:

        这会引发错误,因为您要添加相同的密钥两次。尝试使用Dictionary 而不是HashTable

        Dictionary<int, IList<string>> values = new Dictionary<int, IList<string>>();
        IList<string> list = new List<string>()
        {
            "test", "Test1"
        };
        values.Add(1, list);
        

        【讨论】:

        • IList 用于动态存储+按索引获取。只是动态存储是`ICollection,不是吗?
        • 当然,看他想要什么,他可以使用IEnumerableICollectionIListstring[]...任何他需要的东西
        【解决方案6】:

        可能是 4 年后,但我希望它会在以后对某人有所帮助。 如前文所述,在 Hashtable(key, value) 中,不可能不同的值使用相同的键。虽然,您可以创建一个 List 或一些 object 作为 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]);
        

        然后检索这个数据:

        //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
        

        【讨论】:

          【解决方案7】:

          在哈希表中存储一个列表:

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

          这是一个常见的技巧。

          【讨论】:

          • 如果您确定结果类型,则使用cast,而不是运算符as。无论如何 - 使用泛型集合,而不是 .NET 1.x 非泛型集合。
          【解决方案8】:

          JFYI,你可以这样声明你的 dic:

          Dictionary<int, IList<string>> dic = new
          {
              { 1, new List<string> { "Test1", "test1" },
              { 2, new List<string> { "Test2", "test2" }
          };
          

          【讨论】:

            【解决方案9】:

            您正在寻找一个Lookup,它可以为每个键本机存储多个值。

            正如所指出的,这仅适用于固定列表,因为一旦创建了条目就无法将条目添加到查找中。

            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();
            

            【讨论】:

            • Lookup 是不可变的。这可能很好,但在 OP 场景中可能不起作用。
            【解决方案10】:

            您可以使用 NameValueCollection - 与 hashtable 一样工作并且具有“GetValues()”。

            【讨论】:

              【解决方案11】:

              最好使用我在this library 中使用的两个哈希表

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-07-26
                • 1970-01-01
                • 2013-05-04
                • 2018-10-25
                • 1970-01-01
                • 2023-03-17
                相关资源
                最近更新 更多