Пересечь много списков одним свойством - PullRequest
0 голосов
/ 09 января 2019

у меня List<List<ProductFilter>>

public class ProductFilter
{
    public int Id { get; set; }
    public int FilterValueId { get; set; }
    public int ProductId { get; set; }
    public int? FilterId { get; set; }
    public string FilterValue { get; set; }
    public string FilterName { get; set; }
}

И я хочу Intersect по ProductId и вернуть ProductFilter. Это возможно? Я пробую это:

var intersection = groupList
  .Aggregate((previousList, nextList) => previousList
     .Select(x => x.ProductId)
     .Intersect(nextList.Select(x => x.ProductId))
  .ToList());

но это дает мне ошибку, потому что return int:

Невозможно неявно преобразовать тип 'System.Collections.Generic.List<int>' до 'System.Collections.Generic.List<ProductFilter>'

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Вы получаете указанную ошибку, поскольку ожидается, что функция аккумулятора вернет того же типа, что и элементы в источнике для этой конкретной перегрузки Aggregate то есть List<ProductFilter> вместо List<int>.

Чтобы получить IEnumerable<int> в результате, сначала спроецируйте на IEnumerable<int>, а затем вызовите Aggregate:

groupList.Select(p => p.Select(e => e.ProductId))
         .Aggregate((previousList, nextList) => previousList.Intersect(nextList));
0 голосов
/ 09 января 2019

Для этого вы должны использовать перегрузку Intersect, которая принимает IEqualityComparer<>

class ProductFilterProductIdEqualityComparer : IEqualityComparer<ProductFilter>
{
    public bool Equals(ProductFilter x, ProductFilter y)
    {
        if (ReferenceEquals(x, y))
            return true;
        if (ReferenceEquals(x, null))
            return false;
        if (ReferenceEquals(y, null))
            return false;
        return x.ProductId == y.ProductId;
    }

    public int GetHashCode(ProductFilter obj) => obj.ProductId;
}
var productFilterProductIdEqualityComparer = new ProductFilterProductIdEqualityComparer();
var intersection = groupList
    .Aggregate((previousList, nextList) => 
        previousList.Intersect(nextList, productFilterProductIdEqualityComparer)
    .ToList());

Примечание: Имейте в виду, что когда два ProductFilter имеют одинаковое ProductId, но отличаются от других свойств, вы получите только первое в intersection

...