2009-11-06 42 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行列表來處理你可以直接綁定的行,第一個會給你一堆包含單獨行的組。