Bad Dub
Bad Dub

Reputation: 1593

Distinct or Group By Based on Two Interchangeable Columns (LINQ)

I have a list with the following items

enter image description here

What I would like to do is perform some kind of grouping or distinct using linq based purely on the team names. For the example provided only one record would be returned as its the same teams playing each other even though the names are stored in different variables in the record.

It doesn't matter which record is returned.

Thanks for any help in advance!

Upvotes: 0

Views: 80

Answers (2)

Stuart
Stuart

Reputation: 5496

You could use a custom comparer:

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var fixtures = new List<Match> {
            new Match { Team1 = "Eagles", Team1Score = 2, Team2 = "Hawks", Team2Score = 4},
            new Match { Team1 = "Hawks", Team1Score = 1, Team2 = "Eagles", Team2Score = 2 },
        };

        var results = fixtures
            .GroupBy(x => x, new MatchComparer())
            .Select(x => new { x.Key.Team1, x.Key.Team2, Team1Total = x.Sum(s => s.Team1Score), Team2Total = x.Sum(s => s.Team2Score) });
    }
}

public class MatchComparer : IEqualityComparer<Match>
{
    public bool Equals(Match x, Match y)
    {
        return (x.Team1 == y.Team1 && x.Team2 == y.Team2) ||
            (x.Team1 == y.Team2 && x.Team2 == y.Team1);
    }

    public int GetHashCode(Match obj)
    {
        return obj.Team1.GetHashCode() + obj.Team2.GetHashCode();
    }
}

public class Match
{
    public string Team1 { get; set;}
    public int Team1Score { get; set; }
    public string Team2 { get; set; }
    public int Team2Score { get; set; }
}

Upvotes: 1

Ivan Stoev
Ivan Stoev

Reputation: 205539

One way I can think of is to group by a "normalized" composite key, where normalized means for instance the first key being the smaller of the two and the second being the bigger:

var result = input
    .GroupBy(x => new
    {
        K1 = string.Compare(x.Team1, x.Team2) < 0 ? x.Team1 : x.Team2,
        K2 = string.Compare(x.Team1, x.Team2) < 0 ? x.Team2 : x.Team1,
    })
    .Select(g => g.First())
    .ToList();

Upvotes: 3

Related Questions