2013-03-21 64 views
0

我有一个包含多条记录的datarows集合newLinks。这里是表结构Linq RemoveAll删除所有项目

LinkSysId | LinkId | Col1 | Col2 
1   1  str str1 
2   1  str5 str4 
3   2  str2 str3 
4   2  str6 str7 

我希望做一个LINQ查询,这将遍历集合,只留下顶部1不同的链路ID记录:

LinkSysId | LinkId | Col1 | Col2 
1   1  str str 
3   2  str3 str3 

我试图做这样的

newLinks.RemoveAll(rowComp => newLinks.Any(rowDel => 
        rowComp["linkId"].ToString() == rowDel["linkId"].ToString() 
        && rowComp["linkSysId"].ToString() != rowDel["linkSysId"].ToString())); 

但它删除集合中的所有项目?感谢您的帮助

+0

有趣的是,标题听起来像一切顺利。 – 2013-03-21 13:36:13

+0

@GertArnold我真的很惊讶,因为它会在迭代整个列表之后进行删除。我认为这种逻辑的原因是在迭代中避免万圣节问题。 – Alex 2013-03-21 13:39:40

+0

请注意,'RemoveAll'根本不是LINQ的一部分。这是'List'的方法,而不是'Enumerable'。 – Servy 2013-03-21 13:55:23

回答

1

“创建新”的方法:

DataTable keepTheseRows = table.AsEnumerable() 
    .GroupBy(r => r.Field<int>("LinkId")) 
    .Select(g => g.First()) // takes the first of each group arbitrarily 
    .CopyToDataTable(); 
+0

谢谢你,你的代码解决了我的问题 – Alex 2013-03-21 14:03:06

3

有实现DistinctBy(),这是你在找什么LINQ扩展库。然而这个小片断利用,如果相同的项目已添加Add()方法对HashSet的方法返回false的事实:

var foundIds = new HashSet<int>(); 
var FirstLinkId = newLinks.Where(row=>foundIds.Add(row.LinkId)).ToList(); 
+0

这当然是通常实现'Distinct'的方式,只需要一点额外的逻辑就可以有一个单独的选择器,一个键比较器,参数验证,等等。这是LINQ'Dictinct'或大多数自定义'DistinctBy'实现的核心。 – Servy 2013-03-21 13:56:47

1

由于Tormod说,最好的办法是使用DistinctBy()实现。

(尤其是看Tormod的实现,你会看到它实际上是相同的,如下DistinctByImpl()方法,所以这个答案应该被视为是他的扩展。)

如果使用DistinctBy()时,溶液变得简单:

var uniques = list.DistinctBy(item => item.LinkId);

一个好的实施DistinctBy()可以在Jon Skeet's MoreLinq library这也是available on NuGet找到。

举个例子,下面是一个使用MoreLinq的DistinctBy()实现副本的实现。不要使用此代码 - 使用NuGet下载原始注释代码。

using System; 
using System.Linq; 
using System.Collections.Generic; 

namespace Demo 
{ 
    public static class Program 
    { 
     public static void Main(string[] args) 
     { 
      List<Test> list = new List<Test> 
      { 
       new Test(1, 1), 
       new Test(2, 1), 
       new Test(3, 2), 
       new Test(4, 2) 
      }; 

      var uniques = list.DistinctBy(item => item.LinkId); 

      foreach (var item in uniques) 
      { 
       Console.WriteLine(item); 
      } 
     } 
    } 

    public class Test 
    { 
     public Test(int linkSysId, int linkId) 
     { 
      LinkSysId = linkSysId; 
      LinkId = linkId; 
     } 

     public override string ToString() 
     { 
      return string.Format("LinkSysId = {0}, LinkId = {1}", LinkSysId, LinkId); 
     } 

     public int LinkSysId; 
     public int LinkId; 
    } 

    static class EnumerableExt 
    { 
     public static IEnumerable<TSource> DistinctBy<TSource, TKey> 
      (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) 
     { 
      return source.DistinctBy(keySelector, null); 
     } 

     public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, 
      Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer) 
     { 
      if (source == null) throw new ArgumentNullException("source"); 
      if (keySelector == null) throw new ArgumentNullException("keySelector"); 
      return DistinctByImpl(source, keySelector, comparer); 
     } 

     private static IEnumerable<TSource> DistinctByImpl<TSource, TKey>(IEnumerable<TSource> source, 
      Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer) 
     { 
      var knownKeys = new HashSet<TKey>(comparer); 
      return source.Where(element => knownKeys.Add(keySelector(element))); 
     } 
    } 
}