如何使用LINQ从数组列表中检索一组唯一数组?

时间:2013-02-21 11:37:28

标签: c# arrays linq list

我有这样的结构

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

我可以使用LINQ从propID获取所有唯一值。例如,我有列表     (1,2)     (4,5)     (1,5)     (1,2)     (1,5) 我必须得到     (1,2)     (4,5)     (1,5)

6 个答案:

答案 0 :(得分:3)

您可以使用采用相等比较器的Enumerable.Distinct重载。

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());

如果您想要大于对的集合:

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();
        }
    }
}

如果您的所有int数组都是两个元素,那么您也可以使用Tuple代替Distinct而不使用自定义相等比较器:

IEnumerable<Tuple<int, int>> propIDs = [] { Tuple.Create(1,2), … };
IEnumerable<Tuple<int, int>> distinctPairs = propIDs.Distinct();

答案 1 :(得分:1)

以下是您需要的完整且有效的应用程序。

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;
            }
        }

    }
}

答案 2 :(得分:1)

此代码适用于任何长度数组。

    class MyEqualityComparer : IEqualityComparer<int[]>
    {
        public bool Equals(int[] item1, int[] item2)
        {
            if (item1 == null && item2 == null)
                return true;
            if ((item1 != null && item2 == null) ||
                    (item1 == null && item2 != null))
                return false;
            return item1.SequenceEqual(item2);
        }

        public int GetHashCode(int[] item)
        {
            if(item == null)
            {
                return int.MinValue;
            }
            int hc = item.Length;
            for (int i = 0; i < item.Length; ++i)
            {
                hc = unchecked(hc * 314159 + item[i]);
            }
            return hc;
        }
    }

和distinct的代码:

var result = propIDs.Distinct(new MyEqualityComparer());

答案 3 :(得分:1)

假设您不能使用已提供相等性的Tuple<T1, T2>,您可以创建自己的IEqualityComparer<T>,通过简单地要求所有元素按顺序相等来定义数组的相等性:

class ArrayEqualityComparer<T> : IEqualityComparer<T[]> {

  public Boolean Equals(T[] x, T[] y) {
    if (x.Length != y.Length)
      return false;
    return x.Zip(y, (xx, yy) => Equals(xx, yy)).All(equal => equal);
  }

  public Int32 GetHashCode(T[] obj) {
    return obj.Aggregate(0, (hash, value) => 31*hash + value.GetHashCode());
  }

}

然后您可以轻松获得不同的值:

var distinctPropIDs  = propIDs.Distinct(new ArrayEqualityComparer<Int32>());

答案 4 :(得分:0)

public return List<Tuple<double, double>> uniquePairs(List<double[]> lst)
{
HashSet<Tuple<double, double>> hash = new HashSet<Tuple<double, double>>();
for (int i = 0; i < lst.count; i++)
{
hash.Add(new Tuple<double, double>(lst[i][0], lst[i][1]))
}
List<Tuple<double, double>> lstt = hash.Distinct().ToList();
}

For example:
List<double[]> lst = new List<double[]> {new double[] { 1, 2 }, new double[] { 2, 3 }, new double[] { 3, 4 }, new double[] { 1, 4 }, new double[] { 3, 4 }, new double[] { 2, 1 }}; //  this list has 4 unique numbers, 5 unique pairs, the desired output would be the 5 unique pairs (count = 5)
List<Tuple<double, double>> lstt = uniquePairs(lst);
Console.WriteLine(lstt.Count().ToString());

输出为5

答案 5 :(得分:-1)

HashSet,一个集合是一个不包含重复元素的集合:

var propIDs = HashSet<Tuple<int,int>>