В C # GroupBy свойство, которое является списком - PullRequest
1 голос
/ 29 марта 2019

Группировка по свойство, которое List<T> не работает.
Как лучше всего это настроить?

var blocks = new List<Block>();

blocks.Add(new Block()
{
    Id = 1,
    Values = new List<int>() {1, 2}
});

blocks.Add(new Block()
{
    Id = 1,
    Values = new List<int>() { 2, 3 }
});

blocks.Add(new Block()
{
    Id = 2,
    Values = new List<int>() { 1, 2 }
});

blocks.Add(new Block()
{
    Id = 2,
    Values = new List<int>() { 2, 3 }
});

// here I have 2 groups, which is good
var g1 = blocks.GroupBy(b => b.Id);
// here I have 4 groups, I expected 2
var g2 = blocks.GroupBy(b => b.Values);

public class Block
{
    public int Id { get; set; }
    public List<int> Values { get; set; }
}

1 Ответ

6 голосов
/ 29 марта 2019

Поскольку вы собираетесь сравнивать список, вы должны предоставить компаратор (какие списки считаются равными?) В случае, если списки равны тогда и только тогда, когда они имеют одинаковых элементов в одинаковыхorder :

{1, 2} != {1}        // wrong items number
{1, 2} != {1, 2, 3}  // wrong items number
{1, 2} != {1, 3}     // wrong items values
{1, 2} != {2, 1}     // wrong items order 
{1, 2} == {1, 2}

для сравнения может быть

public class MyListComparer<T> : IEqualityComparer<List<T>> {
  public bool Equals(List<T> x, List<T> y) {
    return Enumerable.SequenceEqual(x, y);
  }

  public int GetHashCode(List<T> obj) {
    return obj == null ? -1 : obj.Count;
  }
}

и Linq

var g2 = blocks.GroupBy(b => b.Values, new MyListComparer<int>());

Редактировать: Если мы хотим игнорировать порядок, мы можем реализовать немного другой компаратор:

public class MyLeanListComparer<T> : IEqualityComparer<List<T>> where T : IComparable<T> {
  public bool Equals(List<T> x, List<T> y) {
    if (ReferenceEquals(x, y))
      return true;
    else if (null == x || null == y)
      return false;

    return Enumerable.SequenceEqual(x.OrderBy(item => item), y.OrderBy(item => item));
  }

  public int GetHashCode(List<T> obj) {
    return obj == null ? -1 : obj.Count;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...