带强制唯一值的.Net字典

时间:2013-09-16 15:50:35

标签: c# .net

是否可以强制词典具有唯一值?请参阅以下示例。

Dictionary<string, string> types = new Dictionary<string, string>()
{
        {"1", "one"},
        {"2", "two"},
        {"3", "three"}
};

如果有人试图执行以下行,则会收到错误。

types.Add("4","one");

我知道这不是字典的构建方式,而正确的答案可能是使用不同的/自定义数据结构。

4 个答案:

答案 0 :(得分:10)

保留两个数据结构;您的常规字典和值HashSet<string>。如果要添加项目,请先检查该值是否在哈希集中。如果不是,那么你知道添加到字典和集合是安全的。 (还要确保在删除时从两个集合中删除项目。)

如果在足够的地方完成此操作,则可能值得创建自己的IDictionary<K,V>实施,该实施内部使用常规DictionaryHashSet,因此您不需要在使用它时做了这么多工作。如果这个特定的结构仅在少数地方使用,那么创建这样一个类可能不值得投资。

答案 1 :(得分:6)

您可能希望实现IDictionary并在内部调用相应的Dictionary<TKey,TValue>方法。此外,您需要HashSet<TValue>。然后,在您的添加方法上,您首先要检查是否hashset.Contains(value)。如果是,则抛出异常。

另一方面,你真的需要这种行为吗?如果你只使用HashSet<Tuple<string,string>>怎么办?然后,任何重复项都会被忽略。或者你真的需要数据结构来抛出异常吗?如果你不这样做,那就是我要去的地方。

编辑:好点@Alexei Levenkov。如果您使用不同的键具有相同的值,则HashSet方法不会提供您最初请求的内容。这只适用于您期望SAME键/值对的情况。

答案 2 :(得分:4)

在添加

之前检查types.ContainsValue
string str = "one";
if (!types.ContainsValue(str)) //doesn't add if its already there
{
    types.Add("4", str);
}

答案 3 :(得分:3)

不幸的是,

框架提供的Dictionary不提供此功能。 最快的解决方法是建立这样的东西

public class UniqueValueDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    public new void Add(TKey key, TValue value)
    {
        if (this.ContainsValue(value))
        {
            throw new ArgumentException("value already exist");
        }
        base.Add(key, value);
    }

    public new TValue this[TKey key]
    {
        get
        {
            return base[key];
        }
        set
        {
            if (this.ContainsValue(value))
            {
                throw new ArgumentException("value already exist");
            }

            base[key] = value;
        }
    }
}

或类似以下内容(性能更好但内存更好)

public class UniqueValueDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    Dictionary<TValue, TKey> valueAsKey = new Dictionary<TValue, TKey>();

    public new void Add(TKey key, TValue value)
    {
        if (valueAsKey.ContainsKey(value))
        {
            throw new ArgumentException("value already exist");
        }
        base.Add(key, value);
        valueAsKey.Add(value, key);
    }

    public new TValue this[TKey key]
    {
        get
        {
            return base[key];
        }
        set
        {
            if (valueAsKey.ContainsKey(value))
            {
                throw new ArgumentException("value already exist");
            }

            if (!this.ContainsKey(key))
            {
                this.Add(key, value);
            }
            else
            {
                base[key] = value;
                valueAsKey[value] = key;
            }
        }
    }

    //You may need to handle remove as well
}

注意:这仅在您使用UniqueValueDictionary<TKey, TValue>类型时才有效。如果您转换为Dictionary<TKey, TValue>,则可以添加重复值。

正如评论中所指出的那样,您可以构建类似这样的内容,继承自IDictionary<TKey, TValue>而不是Dictionary<TKey, TValue>

相关问题