Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I retrieve a set of unique arrays from a list of arrays using LINQ?

Tags:

arrays

c#

list

linq

I have such construction

List<int[]> propIDs = new List<int[]>();

Can I get all unique value from propIDs with LINQ.For example I have list of (1,2) (4,5) (1,5) (1,2) (1,5) and I must get (1,2) (4,5) (1,5)

like image 463
Mykhalik Avatar asked Feb 21 '13 11:02

Mykhalik


2 Answers

You can use the overload of Enumerable.Distinct that takes an equality comparer.

class IntPairArrayComparer : IEqualityComparer<int[]>
{
    public bool Equals(int[] left, int[] right)
    {
        if (left.Length != 2) throw new ArgumentOutOfRangeException("left");
        if (right.Length != 2) throw new ArgumentOutOfRangeException("right");

        return left[0] == right[0] && left[1] == right[1];
    }

    public int GetHashCode(int[] arr)
    {
        unchecked
        {
            return (arr[0].GetHashCode() * 397) ^ arr[1].GetHashCode();
        }
    }
}

IEnumerable<int[]> distinctPairs = propIDs.Distinct(new IntPairArrayComparer());

If you want collections larger than pairs:

class IntArrayComparer : IEqualityComparer<int[]>
{
    public bool Equals(int[] left, int[] right)
    {
        if (left.Length != right.Length) return false;

        return left.SequenceEquals(right);
    }

    public int GetHashCode(int[] arr)
    {
        unchecked
        {
            int hc = 1;

            foreach (int val in arr) hc = hc * 397 ^ val.GetHashCode();
        }
    }
}

If all of your int arrays are two elements long, you could also use Tuples instead which will allow you to use the Distinct without a custom equality comparer:

IEnumerable<Tuple<int, int>> propIDs = [] { Tuple.Create(1,2), … };
IEnumerable<Tuple<int, int>> distinctPairs = propIDs.Distinct();
like image 187
Paul Ruane Avatar answered Oct 13 '22 04:10

Paul Ruane


Below is a complete and working application of your need.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ListsAndArrays
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int[]> propIDs = new List<int[]>();
            propIDs.Add(new[] { 1, 2 });
            propIDs.Add(new[] { 4, 5 });
            propIDs.Add(new[] { 1, 5 });
            propIDs.Add(new[] { 1, 2 });
            propIDs.Add(new[] { 1, 5 });

            var distinct = propIDs.Distinct(new DistinctIntegerArrayComparer());

            foreach (var item in distinct)
            {
                Console.WriteLine("{0}|{1}", item[0], item[1]);
            }

            if (Debugger.IsAttached)
            {
                Console.ReadLine();
            }
        }

        private class DistinctIntegerArrayComparer : IEqualityComparer<int[]>
        {
            public bool Equals(int[] x, int[] y)
            {
                if (x.Length != y.Length) { return false; }
                else if (x.Length != 2 || y.Length != 2) { return false; }

                return x[0] == y[0] && x[1] == y[1];
            }

            public int GetHashCode(int[] obj)
            {
                return -1;
            }
        }

    }
}
like image 27
Mike Perrenoud Avatar answered Oct 13 '22 05:10

Mike Perrenoud