检查字典是否有重复项目

时间:2014-05-07 18:23:16

标签: c#

我有一本字典但是有很多实例可以添加重复数据。我试图阻止添加重复键或值。但是,使用此代码我仍然可以获得"已经添加了具有相同密钥的项目"。我想只在词典中添加新的键和值,如果它们尚未添加到词典中。

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>
}

4 个答案:

答案 0 :(得分:4)

因为如果您遇到具有相同但具有不同的项目,那么它仍会尝试插入它。如果确实想要阻止重复值,那么您需要使用&&代替:

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仅要求Key是唯一的 - 重复Value没有问题。也许你只想要唯一的键/值对?

如果重复的是唯一关注的问题,那么这将是一个正确的方法:

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; 
}

如果密钥存在,使用索引器([]会抛出异常,但会覆盖该密钥的(或者如果密钥不存在)

答案 1 :(得分:3)

您正在使用||,这意味着如果您的字典中的值不存在,那么即使已经添加了密钥,该语句也会评估为 true 。将if语句分开或使用 AND &&)而不是OR

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

答案 2 :(得分:2)

仅检查密钥,而不是值。因为ContainsValue可能会返回false,但已经添加了相同的密钥,在这种情况下,您将获得异常。

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

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

UPDATE1:

您似乎只是担心异常,值得注意的是,重复值会抛出异常,但重复的密钥会出现。

如果您获得重复密钥,如果您决定使用最新到达的值,则可以执行以下操作。

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

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

答案 3 :(得分:1)

如果你真正需要的是唯一键值对,我想你想在这里使用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);

这是有效的,因为元组的默认比较是按值计算的。