C#System.ArgumentException:具有相同键的项已添加

时间:2018-12-07 12:55:36

标签: c#

有人可以建议我如何防止此错误。

错误在这里: dict.Add(sourse [i + 1],target [j + 1]);

using System.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication8
{
    class Program
    {
        static void Main(string[] args)
        {
            var sourse = File.ReadAllLines("1.txt", Encoding.Default);
            var target = File.ReadAllLines("2.txt", Encoding.Default);
            var dict = new Dictionary<string, string>();
            for (int i = 0; i < sourse.Length; i += 2)
            {
                for (int j = 0; j < target.Length; j += 2)
                {
                    if (sourse[i] == target[j])
                    {
                        dict.Add(sourse[i + 1], target[j + 1]);
                        break;
                    }
                }
            }
            var result = File.ReadAllLines("3.txt", Encoding.Default).ToList();
            for (int i = result.Count - 1; i >= 0; i--)
            {
                foreach (var item in dict)
                {
                    if (result[i].EndsWith(item.Key))
                    {
                        result.Insert(i - 1, item.Value);
                        break;
                    }
                }
            }
            File.WriteAllLines("result.txt", result, Encoding.Default);
        }
    }
}

我使用Windows 7 64位。 这段代码正常工作。 昨天停止了工作。

3 个答案:

答案 0 :(得分:2)

更改代码的这一部分:

if (sourse[i] == target[j])
{
    dict.Add(sourse[i + 1], target[j + 1]);
    break;
}

对此:

if (sourse[i] == target[j])
{
    if (!dict.ContainsKey(sourse[i + 1]))
    {
       dict.Add(sourse[i + 1], target[j + 1]);
    }
    break;
}

这将防止添加具有相同键的字典项

答案 1 :(得分:2)

正确的解决方法取决于字典中发生冲突时要执行的操作。如果键已经出现,是否指示错误?如果不是,是要保留现有值,还是将其替换为新值?

如果碰撞表明有错误,那么使用Add是正确的方法,尽管您可能想catch出错并以更“友好”的方式进行报告。

如果要保留原始值,请将Add操作替换为TryAdd,只有在字典中不存在该键时,该操作才会成功:

dict.TryAdd(sourse[i + 1], target[j + 1]);

注意:TryAdd方法已添加到.NET Core 2.0中,并且是.NET Standard 2.1的一部分。如果您的框架版本不提供此功能,则可以用@ tarik-tutuncu的答案中的支票代替它

如果要替换现有值并在其位置添加新值,则可以简单地使用“索引器”语法,该语法具有“添加或替换”语义:

dict[sourse[i + 1]] = target[j + 1];

还有另一种可能性,即您的键和值之间可能存在一对多的关系。如果真是这样,那么简单的字典将无法工作,因为它只能将键映射到单个值。一种解决方法是使用Dictionary<string, List<string>>()

var dict = new Dictionary<string, List<string>>();

for (int i = 0; i < sourse.Length; i += 2) {
    for (int j = 0; j < target.Length; j += 2) {
        if (sourse[i] == target[j]) {
            Add(dict, sourse[i + 1], target[j + 1]);
            break;
        }
    }
}

...其中Add定义为:

private static void Add(Dictionary<string, List<string>> d, string key, string value)
{
    if (!d.TryGetValue(key, out var list))
        d[key] = list = new List<string>();
    list.Add(value);
}

答案 2 :(得分:0)

看起来像“ 1.txt”包含一些重复项。如果这完全有可能,那么您需要确定在这种情况下要做什么。

至少,您可能想要在执行其他任何操作之前评估是否有重复项。在这一点上,您可能要检查“ 1.txt”和“ 2.txt”中的重复行。您可以通过创建以下内容来做到这一点:

public bool HasDuplicates(string[] myValues)
{
    return myValues.GroupBy(x => x).Any(g => g.Count() > 1);
}

此时,如果返回true,则需要决定要做什么。如果他们两个都不应该重复,那么您是否应该抛出异常?

另一方面,如果可能的话,是否需要检查哪些重复项然后删除其中一个?如果是这样,此问题可能会有所帮助:Finding Duplicate String Arrays