1

请原谅我下面的伪代码。我很确定有一种神奇的方法可以在单个 linq 语句中编写它,这也将显着提高性能。在这里,我有一个 AList 中数百万条记录的列表。id 可能不是唯一的。我所追求的是删除所有重复项(基于 id)的原始列表,但始终获取最早日期的记录。当 id 重复时,mystring 几乎总是一个不同的值。

public class A
{
    public string id { get; set; }
    public string mystring { get; set; }
    public DateTime mydate { get; set; }
}

List<A> aListNew = new List<A>();
foreach (var v in AList)
{
    var first = AList.Where(d => d.id == v.id).OrderBy(d => d.mydate).First();

    // If not already added, then we add
    if (!aListNew.Where(t => t.id == first.id).Any())
        aListNew.Add(first);
}
4

3 回答 3

5

您可以在一个 LINQ 语句中直接使用分组来完成此操作:

List<A> aListNew = AList
                   .GroupBy(d => d.id)
                   .Select(g => g.OrderBy(i => i.mydate).First())
                   .ToList();
于 2013-10-03T19:05:40.957 回答
4

最快的可能是foreach带有字典的直接循环:

Dictionary<int, A> lookup = Dictionary<int, A>();

foreach (var v in AList)
{
    if(!lookup.ContainsKey(v.id))
        // add it
        lookup[id] = v;
    else if (lookup[id].mydate > v.mydate)
        // replace it
        lookup[id] = v;    
}

// convert to list
List<A> aListNew = lookup.Values.ToList();

如果冲突很少,则Linq GroupBy/查询可能具有可比性,但其中任何一个都将是 O(N),因为它必须遍历整个列表。First()

于 2013-10-03T19:09:41.410 回答
0

这应该是最简单的。反正不涉及 LINQ。

var lookup = Dictionary<int, A>();
foreach(var a in aListNew.OrderByDescending(d => d.mydate)) {
    lookup[a.id] = a;
} 
var result = lookup.Values.ToList();

请注意,sub-LINQ 会损害性能,这就是我选择不使用它的原因。请记住,LINQ 的存在是为了让您的任务更轻松,而不是让执行更快。

于 2013-10-03T19:19:59.143 回答