【问题标题】:HashSet with Index Access具有索引访问的 HashSet
【发布时间】:2011-10-18 07:15:11
【问题描述】:

我需要一个数据结构

  1. 允许我添加/项目到它
  2. 不允许重复
  3. 通过索引访问集合

我正在考虑哈希集,但HashSet doesn't have an index。满足上述需求的数据结构是什么?

【问题讨论】:

  • 如果您没有绑定到特定的 .NET 版本,@bobbymcr 可能有很好的答案 ;-)

标签: c# hashset


【解决方案1】:

KeyedCollection<TKey, TItem> 派生的集合怎么样?这表示项目的集合,其中每个键都派生自项目本身。默认情况下,它不允许您添加重复项(即具有相同键的项目)。它允许通过键索引查找。

internal class Program
{
    private static void Main(string[] args)
    {
        TestItemCollection items = new TestItemCollection();
        items.Add(new TestItem("a"));
        items.Add(new TestItem("a")); // throws ArgumentException -- duplicate key

        TestItem a = items["a"];
        a = items[0];
    }

    private sealed class TestItem
    {
        public TestItem(string value)
        {
            this.Value = value;
        }

        public string Value { get; private set; }
    }

    private sealed class TestItemCollection : KeyedCollection<string, TestItem>
    {
        public TestItemCollection()
        {
        }

        protected override string GetKeyForItem(TestItem item)
        {
            return item.Value;
        }
    }
}

【讨论】:

    【解决方案2】:

    我想你想要的是Dictionary

    【讨论】:

      【解决方案3】:

      有用吗?

      class MyHashSet<T> : HashSet<T>
      {
          public T this[int index]
          {
              get
              {
                  int i = 0;
                  foreach (T t in this)
                  {
                      if (i == index)
                          return t;
                      i++;
                  }
                  throw new IndexOutOfRangeException();
              }
          }
      }
      

      【讨论】:

      • 当你可以使用 HashSet.Contains() 这是 O(1) 而这是 O(n)...
      • 我会纠正自己,我看到您使用的是 int 索引器,而不是 T 作为索引器(就像字典键一样)
      【解决方案4】:

      我认为您需要开发自己的List 扩展类。 List 可以匹配您的第 1 点和第 3 点,但要匹配第 2 点,您需要覆盖 Add 方法。

      【讨论】:

        【解决方案5】:
        You can do it by extending the HashSet, meat of it to see if it contains the element, and thats O(1), reaturn that  element, so no harm done in that case. Here is the derived one:
        
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Runtime.Serialization;
        
        namespace Tester
        {
            // Summary:
            //     Represents a set of values.
            //
            // Type parameters:
            //   T:
            //     The type of elements in the hash set.
            [Serializable]
            public class HashSetExt<T> : HashSet<T>
            {
                // Summary:
                //     Initializes a new instance of the System.Collections.Generic.HashSetExt<T> class
                //     that is empty and uses the default equality comparer for the set type.
                public HashSetExt() : base() { }
        
                public HashSetExt(IEnumerable<T> collection) : base(collection) { }
                public HashSetExt(IEqualityComparer<T> comparer) : base(comparer) { }
        
                public HashSetExt(IEnumerable<T> collection, IEqualityComparer<T> comparer) : base(collection, comparer) { }
        
                protected HashSetExt(SerializationInfo info, StreamingContext context) : base(info, context) { }
        
                public T this[T item]
                {
                    get
                    {
                        if (this.Contains(item))
                        {
                            return item;
                        }
                        throw new KeyNotFoundException();
                    }
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2016-09-16
          • 1970-01-01
          • 2013-02-08
          • 2020-11-30
          • 2010-11-25
          • 2013-07-17
          • 1970-01-01
          • 2023-04-08
          • 1970-01-01
          相关资源
          最近更新 更多