Reputation: 9194
I am trying to figure out if I can use LINQ to provide me with the distinct values of some data I have in a DataTable (FirstName, LastName, QTY). I can get the distinct values and fill my List, but I have to run two different LINQ queries to get it....I am sure there is a better way to do it :)
Any suggestions would be greatly appreciated (very new to LINQ)
Code:
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;}
Upvotes: 21
Views: 81878
Reputation: 36438
Any reason not to simply do the projection after the distinct, you might need an AsEnumerable() after the Distinct but that's not a big deal.
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();
}
Upvotes: 25
Reputation: 28765
It's not clear from your question whether the quantity is a value in your DataTable, or a count of the number of duplicates for a given item, as in Ecyrb's answer. However, if your StudentData
class implements IEquatable<StudentData>
or overrides the Equals method, this should work:
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();
}
If StudentData
doesn't support value comparison, and you can't add that support to the class, you may have to create an implementation of IEqualityComparer<StudentData>
and pass that into the Distinct
method.
Upvotes: 5
Reputation: 2080
You could use 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; }
}
Upvotes: 1
Reputation: 7491
Pretty sure you could just do this...
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();
Upvotes: 1