2009-11-23 20 views
15

Sto cercando di capire se posso usare LINQ per fornire me con i valori distinti di alcuni dati che ho in un DataTable (Nome, Cognome, QTY). Posso ottenere i valori distinti e riempire la mia lista, ma devo eseguire due query LINQ diverse per ottenerlo .... Sono sicuro che c'è un modo migliore per farlo :)LINQ Get valori distinti e riempire LISTA

Qualsiasi suggerimento sarebbe molto apprezzato (molto nuovo per LINQ)

Codice:

public static List<StudentData> LinqDistinct(DataTable dt) 
{ 
     DataTable linqTable = dt; 

     //get the distinct values 
     var query = 
      (from names in dt.AsEnumerable() 
      select new { 
       FirstName = names.Field<string>("FirstName"), 
       LastName = names.Field<string>("LastName") 
      }).Distinct(); 


     //fill my list with the distinct values 
     List<StudentData> sList = (from sa in query.AsEnumerable() 
            select new StudentData 
               { 
                FirstName = sa.FirstName, 
                LastName = sa.LastName 
                //Qty = names.Field<int>("Qty") 

               }).ToList();            



     return sList;} 

risposta

19

Qual è il motivo per non fare semplicemente la proiezione dopo la distinta, potrebbe essere necessario un AsEnumerable() dopo il netto, ma questo non è un grosso problema.

public static List<StudentData> LinqDistinct(DataTable dt) 
{ 
    DataTable linqTable = dt; 
    return 
     (from names in dt.AsEnumerable() 
     select new { 
      FirstName = names.Field<string>("FirstName"), 
      LastName = names.Field<string>("LastName") 
     }).Distinct().Select(x => 
      new StudentData() { FirstName=x.FirstName, LastName=x.LastName}) 
      .ToList(); 
} 
+0

Ho appena visto questo ... questo è perfetto! Ora non devo nemmeno usare IEqualityComparer !. Grazie. – scarpacci

1

abbastanza sicuro che si può solo fare questo ...

List<StudentData> sList = (from names in dt.AsEnumerable().Distinct() // I am not sure if you even have to call AsEnumerable() 
       select new StudentData() { 
        FirstName = names.Field<string>("FirstName"), 
        LastName = names.Field<string>("LastName") 
       }).ToList(); 
+0

Questo potrebbe non volere, perché stai chiedendo un elenco distinto di oggetti DataRow, che probabilmente faranno confronti di riferimento e decideranno che i tuoi dati sono già distinti. Ma hai bisogno della chiamata AsEnumerable() sul DataTable (solo non sulla query, nel codice originale). –

+0

È possibile che questo ancora non è mi dà le righe distinte che cercavo ... grazie per la risposta però :) S – scarpacci

1

si potrebbe utilizzare GroupBy:

public static List<StudentData> LinqDistinct(DataTable dt) 
{ 
    List<StudentData> results = dt.AsEnumerable() 
     .GroupBy(row => 
     { 
      FirstName = row.Field<string>("FirstName"), 
      LastName = row.Field<string>("LastName") 
     }) 
     .Select(group => new StudentData 
     { 
      FirstName = group.Key.FirstName, 
      LastName = group.Key.LastName, 
      Qty = group.Count() 
     }) 
     .ToList(); 

    return results; 
} 

class StudentData 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int Qty { get; set; } 
} 
+0

darò questo un colpo – scarpacci

5

Non è chiaro dalla tua domanda se la quantità è un valore nel tuo DataTable, o un conteggio del numero di duplicati per un determinato articolo, come nella risposta di Ecyrb. Tuttavia, se la classe StudentData implementa IEquatable<StudentData> o sovrascrive il metodo Equals, questo dovrebbe funzionare:

public static List<StudentData> LinqDistinct(DataTable dt) 
{ 
    return dt.AsEnumerable() 
      .Select(row => new StudentData 
          { 
           FirstName = row.Field<string>("FirstName"), 
           LastName = row.Field<string>("LastName"), 
           Qty = row.Field<int>("Qty") 
          }) 
      .Distinct() 
      .ToList(); 
} 

Se StudentData non supporta il confronto di valore, e non è possibile aggiungere che il sostegno alla classe, potrebbe essere necessario creare un'implementazione di IEqualityComparer<StudentData> e passare che nel metodo Distinct.

+0

mi scuso .... Nome, Cognome, QTY sono in datatable, ma voglio solo restituire FirstName/LastName. Darò un colpo al tuo metodo. Grazie! – scarpacci

+0

+1 penso che questo sia la soluzione migliore ... – bytebender

+0

Questo ha funzionato! Grazie Joel! – scarpacci

Problemi correlati