我有这样的结构
List<int[]> propIDs = new List<int[]>();
我可以使用 LINQ 从 propID 中获取所有唯一值吗?例如,我有 (1,2) (4,5) (1,5) (1,2) (1,5) 的列表,我必须得到 (1,2 ) (4,5) (1,5)
您可以使用采用相等比较器的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
s 代替,这将允许您在Distinct
没有自定义相等比较器的情况下使用:
IEnumerable<Tuple<int, int>> propIDs = [] { Tuple.Create(1,2), … };
IEnumerable<Tuple<int, int>> distinctPairs = propIDs.Distinct();
以下是您需要的完整且有效的应用程序。
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;
}
}
}
}
此代码适用于任何长度的数组。
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;
}
}
和不同的代码:
var result = propIDs.Distinct(new MyEqualityComparer());
假设您不能使用which 已经提供了相等性,您可以通过简单地要求所有元素按顺序相等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>());
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
HashSet,集合是不包含重复元素的集合:
var propIDs = HashSet<Tuple<int,int>>