Renatas Karnauskas
Renatas Karnauskas

Reputation: 21

Avoid duplicates while creating CSV file

So this is the part of the code that I need to modify. I need to make it so that there wouldn't be any duplicates but also in the file on second column should create a number how many times it has been found as a duplicate. It should look like this: https://i.sstatic.net/9xqci.jpg

private static void SaveDataToFile(List<Ring> rings)
{
    using (StreamWriter writer = new StreamWriter(@"Metalai.csv"))
    {
        List<Ring> results = new List<Ring>();
        writer.WriteLine("Metalai");

        foreach (var ring in rings)
            if (!results.Contains(ring))
            {
                writer.WriteLine("{0}", ring.Metalas);
            }
    }
}

Upvotes: 1

Views: 492

Answers (5)

Tim Schmelter
Tim Schmelter

Reputation: 460228

I would use a HashSet<Ring> instead because it's much more efficient. You need to override Equals and GetHashCode in Ring and/or implement IEquatable<Ring>.

However, you can also use this simple approach:

private static void SaveDataToFile(List<Ring> rings)
{
    var metalasLookup = rings.ToLookup(r => r.Metalas);
    using (StreamWriter writer = new StreamWriter(@"Metalai.csv"))
    {
        writer.WriteLine("Metalai");
        foreach (var metalasGroups in metalasLookup)
        {
            int count = metalasGroups.Count();
            string = line $"{metalasGroups.Key},{(count == 0 ? "" : count.ToString())}";
            writer.WriteLine(line);
        }
    }
}

or with a very concise version:

static void SaveDataToFile(List<Ring> rings)
{
    var lines = rings.ToLookup(r => r.Metalas).Select(x => $"{x.Key},{(x.Any() ? x.Count().ToString() : "")}");
    File.WriteAllLines(@"Metalai.csv", lines);
}

Upvotes: 2

arslanaybars
arslanaybars

Reputation: 1853

Labas draugas, I think you are looking for something like this,

static void Main(string[] args)
{
    List<Ring> rings = new List<Ring>();
    rings.Add(new Ring { Id = 1, Name = "siauliai", Metalas = "s" });
    rings.Add(new Ring { Id = 2, Name = "kaunas", Metalas = "k" });
    rings.Add(new Ring { Id = 3, Name = "vilnius", Metalas = "v" });
    rings.Add(new Ring { Id = 4, Name = "klapedia", Metalas = "ka" });
    rings.Add(new Ring { Id = 5, Name = "siauliai", Metalas = "s" });

    SaveDataToFile(rings);

    Console.ReadKey();
}

private static void SaveDataToFile(List<Ring> rings)
{
    using (StreamWriter writer = new StreamWriter(@"Metalai.csv"))
    {
        List<string> ringMetalas = new List<string>();
        writer.WriteLine("Metalai;Duplication");

        foreach (var ring in rings)
        {
            if (!ringMetalas.Contains(ring.Metalas))
            {
                var duplicationCount = rings.Count(r => r.Metalas == ring.Metalas);
                ringMetalas.Add(ring.Metalas);

                var mesage = $"{ring.Metalas}";
                if (duplicationCount > 1)
                    mesage += $";{duplicationCount}";

                writer.WriteLine("{0}", mesage);
            }
        }
    }
}

Result Like;

Metalai Duplication
s       2
k   
v   
ka  

Hope its help to you

Upvotes: 2

LukeChastain
LukeChastain

Reputation: 94

First you'll want Ring to implement Equals() and have a decent GetHashCode(). Then use a Dictionary where the value is count. It's not fancy, but its clear.

Upvotes: 1

Marcus
Marcus

Reputation: 450

Consider sorting rings before you start creating your csv-file to lower the computational effort. In the sorted case you know that duplicates would show up next to each other, thus, when writing rings(15) you only have to verify that rings(14) is no duplicate. Otherwise you would need to go through the whole rings variable ech and every time which increases the effort.

So for the sorted case this could be a solution:

private static void SaveDataToFile(List<Ring> rings)
{
    using (StreamWriter writer = new StreamWriter(@"Metalai.csv"))
    {
        List<Ring> results = new List<Ring>();
        writer.WriteLine("Metalai");
        String oldRing = String.empty;
        int duplicates = 0;
        foreach (var ring in rings)
            if (!results.Contains(ring))
        {
            if (ring.Metalas == oldRing)
            {
                Console.WriteLine("{0}", ring.Metalas);
                duplicates++;
            }
            else
            {
                writer.WriteLine("{0}", ring.Metalas);
                oldRing = ring.Metalas;
            }
        }
    }
}

Upvotes: 0

tevemadar
tevemadar

Reputation: 13225

Now really...

if(!results.Contains(ring)){
    results.Add(ring);
    writer....
} else {
    duplicates++;
}

where 'duplicates' would be your counter counting duplicates. Start it from 0.

Upvotes: 1

Related Questions