【问题标题】:C# Dictionary: Each Key Has An Identical Value - Can I Remove the Redundancy?C# 字典:每个键都有一个相同的值 - 我可以删除冗余吗?
【发布时间】:2009-12-03 18:45:06
【问题描述】:

考虑以下代码,其中每个键都有相同的值:

IDictionary<string, string> quarterbackDictionary = new Dictionary<string, string>();
quarterbackDictionary.Add("Manning", "Manning");
quarterbackDictionary.Add("Brady", "Brady");
quarterbackDictionary.Add("Rivers", "Rivers");

我的问题:

  • 我可以删除冗余,这样我就不必重复每个 字符串两次,类似于 以下:
IDictionary<string, string> quarterbackDictionary = new Dictionary<string, string>();
quarterbackDictionary.Add("Manning");
quarterbackDictionary.Add("Brady");
quarterbackDictionary.Add("Rivers");

仅供参考:

  • 我正在使用字典,因为我想尝试插入重复键。
  • HashSet 将不会尝试插入重复键。

【问题讨论】:

  • 为什么必须key == value?为什么不按照 driis 的建议使用 d.Add("Manning", null)HashSet

标签: .net c#-3.0 dictionary syntactic-sugar


【解决方案1】:

您可以将HashSet<string> 包装在您自己的类中,如果您尝试两次添加相同的键,它会引发异常。

定义该类不会很麻烦,事实上,这里有一个可能的实现,您可以根据需要进行调整:

    public class UniqueHashSet<T> : ICollection<T>
    {
        private readonly HashSet<T> innerSet = new HashSet<T>();

        public void Add(T item)
        {
            if (innerSet.Contains(item))
                throw new ArgumentException("Element already exists", "item");
            innerSet.Add(item);
        }

        public void Clear()
        {
            innerSet.Clear();
        }

        public bool Contains(T item)
        {
            return innerSet.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            innerSet.CopyTo(array, arrayIndex);
        }

        public bool Remove(T item)
        {
            return innerSet.Remove(item);
        }

        public int Count
        {
            get { return innerSet.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return innerSet.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return innerSet.GetEnumerator();
        }
    }

正如其他答案所提到的,您也可以将其设为扩展方法。我认为您当然可以这样做,除非您需要绝对确定不能两次添加相同的项目(如果您以扩展方法的方式进行,仍然可以调用常规的 .Add 方法)。

【讨论】:

  • -1:我正在使用字典,因为我想尝试插入重复键。
  • 不使用 Dictionary 为什么不使用 HashSet 并添加一个函数,如果键已经存在或将键添加到散列中则抛出异常?
  • @Aaron:正是我的想法。如果您需要抛出异常,请使用(扩展?)函数,其中if (Add == false) throw new Exception();
  • d'oh - 当我输入我的输入时,你们得出了和我一样的结论
【解决方案2】:

为 HashSet 添加一个扩展方法,比如 AddUnique,它只调用 Add 并在返回为 false 时抛出。

【讨论】:

    【解决方案3】:

    也许你可以使用扩展方法

    public static class DictionaryExtensions
    {
        public static void Add(this Dictionary<string, string> dictionary,  
            string keyAndValue)
        {
            string value;
            if (dictionary.TryGetValue(keyAndValue, out value))
            {
                throw new Exception();
            }
    
            dictionary.Add(keyAndValue, keyAndValue);
        }
    }
    

    【讨论】:

    • 我认为扩展方法是可行的方法,但我会将其添加到 HashSet 中。
    • 我可能会选择向 HashSet 添加扩展方法,或者像 driis 那样实现我自己的集合。但是主题启动器似乎已设置为使用 Dictionary 这就是我选择使用它来回答问题的方式。
    • OP (Jim) 表示,“我正在使用字典,因为我想尝试插入重复键”。如果这是我认为 HashSet 更合适的唯一原因。
    • @Phil Nash:哈希集也可以工作。一个或六个中的六个。我也给了你的答案 +1。
    • 谢谢,@Jim G。但是,我认为它是一个 7 中的 5 ;-) 如果 HashSet 是合适的,那么它的优点是存储开销更少(字典将将每个项目存储两次 - 一次用于键,一次用于值)。从概念上讲,这是存储空间的两倍——尽管实际上由于散列和其他开销,它会更少——但可能是一个不错的 1.5 倍
    【解决方案4】:

    System.Collections.ObjectModel.Collection 继承并覆盖InsertItem(受保护)。

    然后您可以进行重复检查并在有人插入重复项时抛出。在任何可以放入新项目的方法上调用 InsertItem:Add、Insert 等。

    【讨论】:

    • System.Collections.ObjectModel.Collection 类仍然是一个基于数组的集合;使用.Contains() 在其中查找项目将花费线性时间。字典的吸引力在于查找时间大致恒定。
    • 很高兴看到该应用程序经过如此高度优化,以至于实际上有所作为。
    【解决方案5】:

    您也可以从System.Collections.ObjectModel.KeyedCollection 继承。

    class MyDictionary : KeyedCollection<string, string>
    {
        protected override string GetKeyForItem(string item)
        {
            return item;
        }
    }
    
    var d = new MyDictionary();
    d.Add("jones");
    d.Add("jones");   // this will except
    

    【讨论】:

    • +1 KeyedCollection 可用于 .NET 2.0。 Hashset 仅在 .NET 3.5 中可用。
    猜你喜欢
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 2021-05-10
    • 2021-09-01
    • 2021-05-10
    • 2021-10-07
    • 2014-05-21
    • 2021-12-24
    相关资源
    最近更新 更多