2013-10-03 40 views
1

请原谅我下面的伪代码。我很确定有一种不可思议的方式可以在单个linq语句中编写这个语句,这也会显着提高性能。我在这里列出了数百万条AList中的记录。该ID可能不是唯一的。我所追求的是删除所有重复项的原始列表(基于id),但始终以最早的日期抓取记录。有重复的id时,mystring几乎总是不同的值。C#Linq有助于提高性能?

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); 
} 

回答

5

你可以直接使用分组在一个LINQ语句来实现这一点:

List<A> aListNew = AList 
        .GroupBy(d => d.id) 
        .Select(g => g.OrderBy(i => i.mydate).First()) 
        .ToList(); 
+0

我不知道我看到你正在检查'aListNew'的成员身份,或者你如何将新元素添加到'aListNew'。 –

+0

@ReacherGilt我正在通过在原始列表上进行分组来完成它。我使用GroupBy通过ID获取项目,并拉出正确的项目,然后将结果转换为列表。这个实现不需要检查。 –

+1

@ReacherGilt这只是使整个操作更加高效和易于遵循。 –

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(); 

A Linq GroupBy/First()如果碰撞很少,查询可能是可比的,b因为它必须遍历整个列表,所以任何一个都将是O(N)。

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(); 

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