列表清单的交集

时间:2015-06-25 14:26:33

标签: c# .net nested-lists

我有一个列表列表,如下所示

public class FilteredVM
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Number { get; set; }
}

 List<List<FilteredVM>> groupedExpressionResults = new List<List<FilteredVM>>();

我想基于ID来截取此列表中的列表,最好的解决方法是什么?

3 个答案:

答案 0 :(得分:4)

这是一种优化的扩展方法:

public static HashSet<T> IntersectAll<T>(this IEnumerable<IEnumerable<T>> series, IEqualityComparer<T> equalityComparer = null)
{
    if (series == null)
        throw new ArgumentNullException("series");

    HashSet<T> set = null;
    foreach (var values in series)
    {
        if (set == null)
            set = new HashSet<T>(values, equalityComparer ?? EqualityComparer<T>.Default);
        else
            set.IntersectWith(values);
    }

    return set ?? new HashSet<T>();
}

使用以下比较器:

public class FilteredVMComparer : IEqualityComparer<FilteredVM>
{
    public static readonly FilteredVMComparer Instance = new FilteredVMComparer();

    private FilteredVMComparer()
    {
    }

    public bool Equals(FilteredVM x, FilteredVM y)
    {
        return x.ID == y.ID;
    }

    public int GetHashCode(FilteredVM obj)
    {
        return obj.ID;
    }
}

就像那样:

series.IntersectAll(FilteredVMComparer.Instance)

你可以写

series.Aggregate((a, b) => a.Intersect(b, FilteredVMComparer.Instance))

但它很浪费,因为它必须构建多套。

答案 1 :(得分:0)

Intersect会在类型为死的时候起作用,在您的情况下,由于您尚未实施GetHashCodeEquals方法,因此无法应用是最好和最完整的方式。

因此,如果您只打算在两个列表中包含elements,那么以下解决方案将适合您。

假设list1list2的类型为List<FilteredVM>,最简单的方法是:

var intersectByIDs = list1.Where(elem => list2.Any(elem2 => elem2.ID == elem.ID));

答案 2 :(得分:0)

如果您是单线解决方案的粉丝,可以使用:

List<FilteredVM> result = groupedExpressionResults.Aggregate((x, y) => x.Where(xi => y.Select(yi => yi.ID).Contains(xi.ID)).ToList());

如果您只想要ID,可以添加.Select(x => x.ID),如下所示:

var ids = groupedExpressionResults.Aggregate((x, y) => x.Where(xi => y.Select(yi => yi.ID).Contains(xi.ID)).ToList()).Select(x => x.ID);

Working Demo