【问题标题】:Check dictionary for duplicate items检查字典中的重复项
【发布时间】:2014-05-07 18:23:15
【问题描述】:

我有一本字典,但在很多情况下可以向其中添加重复数据。我试图防止添加重复的键或值。但是,使用此代码,我仍然会收到“已添加具有相同密钥的项目”。如果尚未将新键和值添加到字典中,我只想将它们添加到字典中。

for (var i = 0; i < nodes.Count; ++i) 
{
    if (!webidsAndXPaths.ContainsKey(nodes[i].Id) || !webidsAndXPaths.ContainsValue(nodes[i].XPath)) // if the key or value does not exist then add it to the dictionary
    webidsAndXPaths.Add(nodes[i].Id, nodes[i].XPath); // now we put the data in a dictionary <key = id, value = xpath>
}

【问题讨论】:

  • 你确定你在这里使用了正确的数据结构吗?
  • 不,我不是,哈哈。想要获取两条数据并将它们写入数据库。有时数据是多余的,所以如果它试图将它添加到字典中,那么它将无法工作。

标签: c#


【解决方案1】:

因为如果您遇到具有相同 key 但不同 value 的项目,那么它仍然会尝试插入它。如果您真的想要防止重复值,那么您需要使用 &amp;&amp; 来代替:

if (!webidsAndXPaths.ContainsKey(nodes[i].Id) &&
    !webidsAndXPaths.ContainsValue(nodes[i].XPath)) // if the key AND value do not exist then add it to the dictionary

但是防止重复的似乎对字典来说是一个奇怪的要求。 Dictionary 只要求Keys 是唯一的——重复的Values 没有问题。也许您只想要唯一的键/值对?

如果重复的 keys 是您唯一关心的问题,那么这将是一种正确的方法:

if (!webidsAndXPaths.ContainsKey(nodes[i].Id)) // if the key does not exist then add it to the dictionary

另一种选择是只设置该值,而不管它是否存在。唯一的区别是找到的 last 值将“获胜”而不是 first

for (var i = 0; i < nodes.Count; ++i) 
{
    webidsAndXPaths[nodes[i].Id] = nodes[i].XPath; 
}

如果键存在,使用索引器 ([]) 不会 抛出异常,但会覆盖该键的 (如果键存在则添加它不存在)

【讨论】:

  • 是的,只要每个条目都是唯一的,就可以重复该值。
  • 如果“entry”是指“key”,那么是的。 Dictionary 中没有内置机制来确保唯一的键值对
  • @DStanley,没错,至少不是Dictionary。然而,Tuple 确实做到了,尽管可能是偶然的 :)
【解决方案2】:

您正在使用||,这意味着如果您的字典中不存在该值,则即使已添加该键,该语句也会评估为 true。使用单独的 if 语句或使用 AND (&amp;&amp;) 而不是 OR

if (!webidsAndXPaths.ContainsKey(nodes[i].Id) &&
     !webidsAndXPaths.ContainsValue(nodes[i].XPath))
{
    webidsAndXPaths.Add(nodes[i].Id, nodes[i].XPath);
}

【讨论】:

    【解决方案3】:

    只检查键,不检查值。因为ContainsValue 有可能返回false,但是已经添加了相同的键,在这种情况下你会得到异常。

    if (!webidsAndXPaths.ContainsKey(nodes[i].Id))
         webidsAndXPaths.Add(nodes[i].Id, nodes[i].XPath); 
    

    如果您需要键和值是唯一的,您可以创建自定义 不可变 结构,其中包含两个属性(Id、Xpath),然后将其添加为键。

    更新1:

    看来你只是担心异常,值得注意的是重复值不会抛出异常,但重复键会。

    如果你得到重复的键,如果你决定使用最新到达的值,你可以这样做。

     webidsAndXPaths[nodes[i].Id] = nodes[i].XPath;
    

    这不会抛出异常,如果已经存在相同的键,它将覆盖该值。

    【讨论】:

    • 所以只有键必须是唯一的,但值可以是重复的?
    • @ma3str0,是的。这就是使密钥成为密钥的原因:唯一且可与任何其他密钥区分开来。这不适用于值,因此您可以将相同的值/相同的对象放在字典中的不同键下。
    • @ma3str0 那么你还需要防止重复键和重复值吗?
    • 我认为只要这对是唯一的那么一切都会好的,我基本上只是不希望冗余数据引发异常并阻止程序执行。
    • @ma3str0 看看我的 Update1 是否有帮助
    【解决方案4】:

    如果你真正需要的是唯一的键值对,我想你想在这里使用Tuple。你可能有这样的事情:

    var kvpList = new List<Tuple<string, string>>();
    

    然后你就可以这样做了:

    var newTuple = Tuple.Create(nodes[i].Id, nodes[i].XPath);
    if (!kvpList.Contains(newTuple))
        kvpList.Add(newTuple);
    

    这是因为元组的默认比较是按值进行的。

    【讨论】:

      猜你喜欢
      • 2020-07-20
      • 1970-01-01
      • 1970-01-01
      • 2017-03-02
      • 2019-01-15
      • 2011-03-21
      • 2013-09-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多