Carel
Carel

Reputation: 2143

Linq conditional group by count

Consider having a workshop table with the following records:

id name
1 Epic Car Repairs
2 Car Care Workshop - Alpha
3 Car Care Workshop - Bravo
4 Car Care Workshop - Charlie
5 Bosch Car Service Centre

Assume all the Car Care Workshop's with id's 2, 3, 4 are part of a franchise. If I have a list of quotes submitted by all of these workshops (assume each of the 5 workshops submitted 1 quote) and assume I have a list of id's for each workshop in the franchise, how do I go about counting the quotes in linq so that all the quotes of the the franchisee workshops count as only 1?

quotes.Count() gives a value of 5

quotes.Count('somehow identify distinct franchises') should give a value of 3

Upvotes: 0

Views: 44

Answers (1)

DaggeJ
DaggeJ

Reputation: 2191

First you need to decide on a way to uniquely identify distinct values, for example name up to the first dash (-). Then you can count distinct values based on this property.

Perhaps something like this;

private class Workshop
{
    public Workshop(int id, string name)
    {
        Id = id;
        Name = name;
    }

    public int Id { get; }
    public string Name { get; }
    public string UniqueName => Name.Split('-').First().Trim();
}

I like to use a helper extension method so that I can get distinct values by a specific property / method.

public static IEnumerable<T> DistinctBy<T, T2>(this ICollection<T> collection, Func<T, T2> selector)
{
    return collection.GroupBy(selector).Select(x => x.First());
}

Your scenario;

[Test]
public void DistinctBy_works()
{
    ICollection<Workshop> collection = new List<Workshop>();
    collection.Add(new Workshop(1, "Epic Car Repairs"));
    collection.Add(new Workshop(2, "Car Care Workshop - Alpha"));
    collection.Add(new Workshop(3, "Car Care Workshop - Bravo"));
    collection.Add(new Workshop(4, "Car Care Workshop - Charlie"));
    collection.Add(new Workshop(5, "Bosch Car Service Centre"));

    var result = collection.DistinctBy(x => x.UniqueName).ToList();
    result.Count.Should().Be(3);
    result[0].Id.Should().Be(1);
    result[1].Id.Should().Be(2);
    result[2].Id.Should().Be(5);
}

Upvotes: 2

Related Questions