Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有强制唯一值的.Net字典_C#_.net - Fatal编程技术网

C# 具有强制唯一值的.Net字典

C# 具有强制唯一值的.Net字典,c#,.net,C#,.net,是否可以强制字典具有唯一的值?请参见下面的示例 Dictionary<string, string> types = new Dictionary<string, string>() { {"1", "one"}, {"2", "two"}, {"3", "three"} }; 我知道字典不是这样建立的,正确的答案可能是使用不同的/自定义的数据结构。在添加之前检查类型。ContainsValue string str =

是否可以强制字典具有唯一的值?请参见下面的示例

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

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

在添加之前检查
类型。ContainsValue

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

您可能希望实现
IDictionary
,并在内部调用相应的
Dictionary
方法。此外,您还需要一个
哈希集。然后,在Add方法上,首先检查
hashset.Contains(value)
。如果是,则抛出异常

另一方面,你真的需要这种行为吗?如果只使用
哈希集
,会怎么样。然后,忽略任何重复项。或者您真的需要数据结构来抛出异常吗?如果你不这样做,我也会这么做


编辑:很好的观点@Alexei Levenkov。如果不同的键具有相同的值,那么HashSet方法就不能满足您最初的要求。只有当您期望相同的键/值对时,这才适用

不幸的是,框架提供的
字典
不提供此功能。 最快的解决方法是构建类似这样的东西

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;
        }
    }
}
公共类UniqueValueDictionary:Dictionary
{
公共新空添加(TKey key,TValue value)
{
if(此.包含值(value))
{
抛出新ArgumentException(“值已存在”);
}
添加(键、值);
}
公共新TValue此[TKey]
{
得到
{
返回基[键];
}
设置
{
if(此.包含值(value))
{
抛出新ArgumentException(“值已存在”);
}
基[键]=值;
}
}
}
或者类似以下内容(性能更好,但内存不足)

公共类UniqueValueDictionary:Dictionary
{
字典值askey=新字典();
公共新空添加(TKey key,TValue value)
{
if(值askey.ContainsKey(值))
{
抛出新ArgumentException(“值已存在”);
}
添加(键、值);
添加(值,键);
}
公共新TValue此[TKey]
{
得到
{
返回基[键];
}
设置
{
if(值askey.ContainsKey(值))
{
抛出新ArgumentException(“值已存在”);
}
如果(!this.ContainsKey(键))
{
添加(键、值);
}
其他的
{
基[键]=值;
valueAsKey[值]=键;
}
}
}
//您可能还需要处理删除
}
注意:这仅在使用
UniqueValueDictionary
类型时有效,如果强制转换为
Dictionary
则可以添加重复的值


正如注释中所指出的,您可以从
IDictionary
而不是
Dictionary
继承这一思想来构建类似的内容

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


如果这是在足够的地方完成的,那么创建您自己的
IDictionary
实现可能是值得的,它在内部使用常规
字典和
哈希集,这样您就不需要在使用它时做太多工作。如果这个特殊的结构只在少数地方使用,那么创建这样一个类可能不值得投资。

因此,为什么不交换
。。。。?是否存在“一”(etc)不能作为此处可接受的
键的原因?请使用不同的/自定义数据结构。可能重复@TimS。这一点都不重复…@Servy好吧,值必须是唯一的,就像键一样,这让人想起了双向字典。我认为这可能会解决他的问题。这是最快的实现,但肯定不是最快的执行。
ContainsValue
检查将为O(n)。使用
ContainsValue
的代码不能是“最快的”-可能是“易于编写”或“易于理解”或“易于支持”。@JimMischel和@Alexei同意你的观点,这只是一个想法。OP可以使optimizations@SriramSakthivel任何优化几乎都涉及到放弃你拥有的一切,重新开始,因此除非他不在乎在这里进行线性搜索,否则答案是好的,如果他不在乎,那就一文不值。还要注意的是,由于
Add
方法不是虚拟的,你只是在跟踪它,这可能是一个严重的问题。这意味着只要对象位于
IDictionary
Dictionary
类型的变量中,它就不会执行这些检查;出于这些原因,您应该封装字典,而不是扩展它,因为这不能可靠地改变这种行为。@Magnus您需要一个
字典
哈希集
。元组将只考虑一个项目,如果两个键和值匹配,而OP认为它是一个复制,如果匹配。+ 1在使用<代码> HASSET。包含(值)< /代码>。请注意
HashSet
HashSet
的问题是,他可能仍然需要查找键的值,而这是不可能的。如果他没有使用数据结构来实际查找某个键的值,那么这可能是正确的方法。@CodesInChaos,是的,如果只需要对该键进行O(1)查找,则可能是正确的方法。相对而言,这将非常慢。每次查找都需要
O(n)
时间。如果你是
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
}