3

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

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

如果有人试图执行以下行,他们应该会收到一个错误。

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

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

4

4 回答 4

12

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

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

于 2013-09-16T16:06:45.710 回答
6

您可能想要实现IDictionary并在内部调用相应的Dictionary<TKey,TValue>方法。另外,你想要一个HashSet<TValue>. 然后,在您的 Add 方法上,您将首先检查您的hashset.Contains(value). 如果是这样,那么你抛出一个异常。

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

编辑:好点@Alexei Levenkov。如果您将使用不同的键获得相同的值,那么 HashSet 方法不会为您提供您最初要求的内容。这仅适用于您期望相同的键/值对。

于 2013-09-16T16:00:40.110 回答
4

types.ContainsValue添加前检查

string str = "one";
if (!types.ContainsValue(str)) //doesn't add if its already there
{
    types.Add("4", str);
}
于 2013-09-16T15:53:33.717 回答
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>将其作为一个想法。

于 2013-09-16T16:01:57.850 回答