georgman
georgman

Reputation: 53

C# System.ArgumentException: An item with the same key has already been added

Can someone advice me how to prevent this error.

Error is here: 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);
        }
    }
}

I use Windows 7 64 bit. This code used to work fine. Yesterday stopped working.

Upvotes: 2

Views: 16829

Answers (3)

Mike Strobel
Mike Strobel

Reputation: 25623

The proper fix depends on what you want to do when there is a collision in the dictionary. If the key already appears, is it indicative of an error? If not, do you want to keep the existing value, or replace it with the new value?

If a collision indicates an error, then using Add is the correct approach, though you may want to catch the error and report it in a more 'friendly' manner.

If you want to retain the original value, replace the Add operation with TryAdd, which will succeed only if the key does not already exist in the dictionary:

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

NOTE: The TryAdd method was added in .NET Core 2.0 and is part of .NET Standard 2.1. If it's not available in your framework version, you can replace it with a check like in @tarik-tutuncu's answer

If you want to replace the existing value and add the new one in its place, you can simply use the 'indexer' syntax, which has "add or replace" semantics:

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

There is another possibility, which is that you may have a one-to-many relationship between your keys and values. If that is the case, a simple dictionary isn't going to work, because it can only map a key to a single value. A workaround would be to use a 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;
        }
    }
}

...where Add is defined as:

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

Upvotes: 2

sr28
sr28

Reputation: 5156

Looks like '1.txt' contains some duplicates. If that's perfectly possible then you need to work out what you want to do in this case.

At the very least you probably want to evaluate whether you have duplicates before doing anything else. At the point you read the lines out of '1.txt' and '2.txt' you probably want to check for duplicates. You can do that by creating something like this:

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

At that point if this returns true you need to decide what to do. If neither of them should have duplicates then should you throw an exception?

On the other hand if this is possible do you need to check which ones are duplicated and then remove one of them? If so this question may help: Finding Duplicate String Arrays

Upvotes: 0

Tarik Tutuncu
Tarik Tutuncu

Reputation: 818

Change this part of your code:

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

to this:

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

this will prevent adding a dictionary item with the same key

Upvotes: 3

Related Questions