2009-11-06 41 views
1

我有一些问题试图从csharp中的数据集检索唯一值,这可能吗?C#数据集 - 基于列检索唯一值

其实我在做这样的事情,从web服务获得的数据集:

webService.getInstructions(Username, Password, AppKey).Tables[0].Select(null, "account name asc"); 

因此,在这种情况下,我从账户按字母顺序排列,但也有在该数据集的一些重复的行。

有没有什么办法,使具有独特“帐号”此数据集的返回值,并通过“帐户名”字母顺序排序呢?

东西代替filterExpression将是非常好的,我认为。 :)

在此先感谢

回答

3

个人而言,我会更改Web服务要做到这一点过滤和在服务器排序,以降低带宽的需求,很可能返回一个简单的数据类型或自定义类(不DataTable或类似的东西)。但是,LINQ将使用定制DistinctBy方法做的工作......(重读问题后更新)

var rows = dataset.Tables[0].AsEnumerable() 
    .DistinctBy(row => row.Field<string>("account number")) 
    .OrderBy(row => row.Field<string>("account name")) 
    .ToArray(); 

static IEnumerable<TSource> DistinctBy<TSource, TValue>(
     this IEnumerable<TSource> source, 
     Func<TSource, TValue> selector) 
    { 
     HashSet<TValue> unique = new HashSet<TValue>(); 
     foreach (var item in source) 
     { 
      if (unique.Add(selector(item))) yield return item; 
     } 
    } 
+0

感谢Marc,它的工作非常好,是的,我完全同意你在Web服务上直接设置这一点,但不幸的是我无法访问它。但感谢您的帮助! :) – zanona 2009-11-06 10:53:59

0

我会用一个小魔术LINQ的数据表。

 DataTable dt = new DataTable(); 
     dt.Columns.Add(new DataColumn("AccountNumber", typeof(System.Int32))); 
     dt.Columns.Add(new DataColumn("AccountName", typeof(System.String))); 

     for (int ii = 0; ii < 20; ii++) 
      dt.Rows.Add(new object[]{ii, "abc" + ii.ToString()}); 

     dt.Rows[6][0] = 5; 
     dt.Rows[7][0] = 5; 
     dt.Rows[8][0] = 5; 

     //using grouping to isolate groups with just one item 
     var groupedRows = from row in dt.Select("", "AccountName ASC") 
          group row by row["AccountNumber"] into rowGroup 
          where rowGroup.Count() == 1 
          select rowGroup; 

     foreach (var group in groupedRows) 
      foreach(DataRow dr in group) 
       Console.WriteLine("Account #: {0} Account name: {1}", dr["AccountNumber"], dr["AccountName"]); 


     //using nested select to avoid grouping 
     Console.WriteLine(); 
     Console.WriteLine("Nested select"); 
     var z = from row in dt.Select() 
       where (from x in dt.Select() where (int) x["AccountNumber"] == (int) row["AccountNumber"] select x).Count() == 1 
       orderby row["AccountName"] 
       select row; 

     foreach(DataRow dr in z) 
      Console.WriteLine("Account #: {0} Account name: {1}", dr["AccountNumber"], dr["AccountName"]); 


     Console.WriteLine(); 
     Console.WriteLine("Datatable select"); 
     var y = from row in dt.Select() 
       where (from x in dt.Select("AccountNumber = " + row["AccountNumber"]) select x).Count() == 1 
       orderby row["AccountName"] 
       select row; 

     foreach (DataRow dr in y) 
      Console.WriteLine("Account #: {0} Account name: {1}", dr["AccountNumber"], dr["AccountName"]); 

将结果打印到屏幕上,注意AccountNumber为'5'的任何行都缺失,因为它不是唯一的。另请注意,在第一个示例中,我使用dataTable.Select()来执行排序,因为排序是相同的,不管由于不是唯一而删除了哪些行。第二个和第三个样本会给你一个IEnumerable行列表来处理你可以直接绑定的行,第一个会给你一堆包含单独行的组。