martijn
martijn

Reputation: 495

group a list and only get distinct values when input is a list

I need some help with the following:

I have a list where all the duplicate entries need to be removed from and I cant seem to get the right linq query. now the list itself contains a string and a list of strings as parameters.

see the code snippets:

the list is created from this class

public class SD
{
    public string From { get; set; }
    public List<string> To { get; set; }
}

the input of the list may look like this:

var unsortedList = new List<SD>
{
    new SD {From = "a", To = new List<string>{ "b" } },
    new SD {From = "b", To = new List<string>{ "a" } },
    new SD {From = "a", To = new List<string>{ "b", "c" } },
    new SD {From = "a", To = new List<string>{ "b" } },
    new SD {From = "a", To = new List<string>{ "c" } },
};

Before the To in the class was a list and just was a string the below code was working perfect. It would return 4 entries as entry 1 and 4 are equal (and off course the 3rd entry would only have one string).

var sortedList = unsortedList.GroupBy(x => new { x.From, x.To }).Select(group => group.First()).ToList();

I've been playing around with orderby, group and hashsets but none seems to work.

Upvotes: 3

Views: 1726

Answers (2)

Pavel Anikhouski
Pavel Anikhouski

Reputation: 23228

You can join To list into string and use it as part of key selector in GroupBy method. Then select the first item in every group to get a list of SD items without duplicates

var sortedList = unsortedList.GroupBy(x => new {x.From, To = string.Join(",", x.To)})
    .Select(g => g.First())
    .ToList();

foreach (var item in sortedList) 
    Console.WriteLine($"{item.From} {string.Join(",", item.To)}");

It'll produce the following output

a b
b a
a b,c
a c

Upvotes: 2

RoadRunner
RoadRunner

Reputation: 26315

You could create a custom IEqualityComparer<T> here:

public class MyComparer : IEqualityComparer<SD>
{
    public bool Equals(SD x, SD y)
    {
        return x.From == y.From && x.To.SequenceEqual(y.To);
    }

    public int GetHashCode(SD obj)
    {
        return obj.From.GetHashCode();
    }
}

Then apply this comparer to Distinct() to remove duplicates:

var noDuplicates = unsortedList.Distinct(new MyComparer());

foreach (var item in noDuplicates)
{
    Console.WriteLine($"From={item.From} To={string.Join(", ", item.To)}");
}

// From=a To=b
// From=b To=a
// From=a To=b, c
// From=a To=c

Upvotes: 1

Related Questions