Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove duplicate pairs in a List

I got a List with pairs of integers. How do I remove pairs if they're duplicates? Distinct wont work cause the pair could be (2, 1) instead of (1, 2).

My list looks like this:

1, 2
2, 3
3, 1
3, 2
2, 4
4, 3

... I don't need (2, 3) and (3, 2)

I made a public struct FaceLine with public int A and B, then var faceline = new List<FaceLine>();.

I'm new to C# and lost.

like image 948
johnny_vonri Avatar asked May 29 '18 12:05

johnny_vonri


People also ask

How do you avoid duplicates in lists?

If you don't want duplicates, use a Set instead of a List . To convert a List to a Set you can use the following code: // list is some List of Strings Set<String> s = new HashSet<String>(list); If really necessary you can use the same construction to convert a Set back into a List .


2 Answers

You could use a custom IEqualityComparer<FaceLine>:

public class UnorderedFacelineComparer : IEqualityComparer<FaceLine>
{
    public bool Equals(FaceLine x, FaceLine y)
    {
        int x1 = Math.Min(x.A, x.B);
        int x2 = Math.Max(x.A, x.B);
        int y1 = Math.Min(y.A, y.B);
        int y2 = Math.Max(y.A, y.B);
        return x1 == y1 && x2 == y2;
    }

    public int GetHashCode(FaceLine obj)
    {
        return obj.A ^ obj.B;
    }
}

Then the query was very simple:

var comparer = new UnorderedFacelineComparer();
List<FaceLine> nonDupList = faceLine
    .GroupBy(fl => fl, comparer)
    .Where(g => g.Count() == 1)
    .Select(g => g.First())
    .ToList();

If you wanted to keep one of the duplicates you just need to remove the Where:

List<FaceLine> nonDupList = faceLine
    .GroupBy(fl => fl, comparer)
    .Select(g => g.First())
    .ToList();
like image 54
Tim Schmelter Avatar answered Oct 26 '22 20:10

Tim Schmelter


If you're happy using the common DistinctBy Linq extension (available via NuGet) you can do this fairly simply like so:

var result = list.DistinctBy(x => (x.A > x.B) ? (x.A, x.B) : (x.B, x.A));

Sample console app:

using System;
using System.Collections.Generic;
using MoreLinq;

namespace Demo
{
    class Test
    {
        public Test(int a, int b)
        {
            A = a;
            B = b;
        }

        public readonly int A;
        public readonly int B;

        public override string ToString()
        {
            return $"A={A}, B={B}";
        }
    }

    class Program
    {
        static void Main()
        {
            var list = new List<Test>
            {
                new Test(1, 2),
                new Test(2, 3),
                new Test(3, 1),
                new Test(3, 2),
                new Test(2, 4),
                new Test(4, 3)
            };

            var result = list.DistinctBy(x => (x.A > x.B) ? (x.A, x.B) : (x.B, x.A));

            foreach (var item in result)
                Console.WriteLine(item);
        }
    }
}
like image 3
Matthew Watson Avatar answered Oct 26 '22 22:10

Matthew Watson