@ Решение Мэтью Уайтеда было бы хорошо, если вы знаете, как группировать колонки заранее.Тем не менее, похоже, что вам нужно определить их во время выполнения.В этом случае вы можете создать компаратор равенства, который определяет равенство строк для GroupBy
, используя настраиваемый набор столбцов:
rows.GroupBy(row => row, new ColumnComparer(0, 1, 2))
Компаратор проверяет равенство значений каждого указанного столбца.Он также объединяет хэш-коды каждого значения:
public class ColumnComparer : IEqualityComparer<object[]>
{
private readonly IList<int> _comparedIndexes;
public ColumnComparer(params int[] comparedIndexes)
{
_comparedIndexes = comparedIndexes.ToList();
}
#region IEqualityComparer
public bool Equals(object[] x, object[] y)
{
return ReferenceEquals(x, y) || (x != null && y != null && ColumnsEqual(x, y));
}
public int GetHashCode(object[] obj)
{
return obj == null ? 0 : CombineColumnHashCodes(obj);
}
#endregion
private bool ColumnsEqual(object[] x, object[] y)
{
return _comparedIndexes.All(index => ColumnEqual(x, y, index));
}
private bool ColumnEqual(object[] x, object[] y, int index)
{
return Equals(x[index], y[index]);
}
private int CombineColumnHashCodes(object[] row)
{
return _comparedIndexes
.Select(index => row[index])
.Aggregate(0, (hashCode, value) => hashCode ^ (value == null ? 0 : value.GetHashCode()));
}
}
Если это то, что вы будете делать часто, вы можете поместить его в метод расширения:
public static IGrouping<object[], object[]> GroupByIndexes(
this IEnumerable<object[]> source,
params int[] indexes)
{
return source.GroupBy(row => row, new ColumnComparer(indexes));
}
// Usage
row.GroupByIndexes(0, 1, 2)
Расширение IEnumerable<object[]>
будет работать только с .NET 4. Вам нужно будет расширить List<object[]>
непосредственно в .NET 3.5.