从列表中删除项目的最佳方法

时间:2015-04-16 10:29:53

标签: c# linq lambda ienumerable

我有一个500.000到1.000.000个MyClass个实例的列表,其中包含以下属性:

class MyClass
{
    string ParentId;
    string Name;
    DateTime StartDate;
    DateTime EndDate;
}

数据可能如下所示:

ParentId | Name    | StartDate    | EndDate
----------------------------------------------
parent1  | alpha   | 01-01-2011   | 02-02-2015
parent1  | beta    | 01-01-2011   | 02-02-2014
parent2  | gamma   | 01-01-2012   | 02-02-2011

我需要过滤列表,使其包含" alpha"和#" gamma"对象。 " beta"应该排除对象,因为它与alpha具有相同的父级,但是更早的EndDate。

即。结果列表应该只包含每个ParentId一个实例(具有最新EndDate的实例)。

过滤需要表现良好。

5 个答案:

答案 0 :(得分:5)

您可以使用GroupBySelect

var filtered = list
              .GroupBy(mc=>mc.ParentId)
              .Select(g=>g.OrderByDescending(mc=>mc.EndDate).First())
              .ToList();

答案 1 :(得分:2)

虽然目前接受的答案(@Kobi)是正确的,可能是最简单的解决方案,但它可能不是“最佳”解决方案。

特别是,既然你提到你可能在列表中有很多项目并且解决方案应该运行良好,我想我会检查没有LINQ的解决方案是如何执行的。

这是我的解决方案:

var tempDict = new Dictionary<string, MyClass>();
foreach (var data in list) // list is the List<MyClass>
{
    MyClass existing;
    if (!tempDict.TryGetValue(data.ParentId, out existing))
    {
        // Put item into temp dictionary (use ParentId as key)
        tempDict[data.ParentId] = data;
    }
    else
    {
        // Check if the instance in the temp dictionary has an
        // earlier EndDate. If yes, replace it.
        if (existing.EndDate < data.EndDate) // replace
            tempDict[data.ParentId] = data;
    }
}

var result = tempDict.Values.ToList();

快速比较(使用500.000项)表明此解决方案比LINQ版本快3到4倍(取决于唯一的ParentId值的数量)。

答案 2 :(得分:1)

我认为您想要根据解释的原因过滤掉测试版,而不是因为它的名字。以下是您可以用来实现这样的结果:

myClasses.GroupBy(i => i.ParentId)
    .Select(i => i.OrderByDescending(i2 => i2.EndDate).First());

答案 3 :(得分:0)

您可以使用List<T>

轻松过滤Linq.Where
var result = myList
    .Where(item => item.Name == "gamma" || item.Name == "alfa")
    .ToList();

如果您想区分某个字段的输出,可以使用MoreLinq's DistinctBy

GroupBy

var result = myList
    .Where(item => item.Name == "gamma" || item.Name == "alfa")
    .GroupBy(item => item.ParentId)
    .Select(g => g.First()) //Selection logic
    .ToList();

答案 4 :(得分:0)

你可以使用它,这个方法可以很好地使用大数组工作:

var groupesList = yourList.GroupBy(x => x.ParentId,
     (y, set) => new {Key = y, Value = set.First(s => s.EndDate == set.Max(r => r.EndDate))}).Select(x => x.Value).ToList();