LINQ - list group by - linq

I am having trouble with a class that has a list of objects - basically it is a shopping cart where you can add items. I wish for the items to be grouped by the item id, so they would not appear more times in the cart.
So if you add an item, and then you add it again, it should appear as 1 row, quantity =2, instead of 2 rows quantity 1.
First of all, is there a way of automatically organizing a list this way?
If not, then I need another var:
var l = from i in list.cartItems
group i by i.id into g
select g.ToList();
list.cartItems = l;
list is the object, cartItems is the list, l would be the new list to "refresh"
However, this causes me an error:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable>' to 'System.Collections.Generic.List'. An explicit conversion exists (are you missing a cast?)
Any ideas?
Thanks
Edit:
I edited the error
Cartitems is just:
public List cartItems;
inside a CartItemList class

You should specify the grouped element you want, like this:
list.cartItems = l.First();
Your cartItems is a 'ListOfItems' type, and your var l is a new grouped type, which is 'int,ListOfItems' type. So to cast your 'int,ListOfItems' to cartItems which is 'ListOfItems', you should choose the element some element from your result collection.

for solve you need change select clause in your query - in select you can apply aggregate function like this:
var l = (from i in list.cartItems
group i by i.id into g
select new CartItem(){Id=g.Key, quantity=g.Count()}).ToList();
list.cartItems = l;
try sample that work
var t = Enumerable.Range(1, 10).Select(i => new { Id = i % 3, Q = 1 }).ToList();
var b = from i in t
group i by i.Id into g
select new { Id = g.Key, Q = g.Count() };
t = b.ToList();
and check your inputs

Related

Is it possible to group by an object property but have the whole object in the Key?

Suppose query is like so:
var query = from x in db.Customers
join y in db.Orders
on x.Id Equals y.CustomerId
where ...
select new {Customer = x, Order = y}
and I want the results grouped by customer:
var resultsByCustomer = query.GroupBy(x => x.Customer.Id)
This works fine, except that now the grouping Key is the customer id, but I want it to be the whole Customer object, because I want to access other properties of that customer (but not properties I want to group by).
I could do this instead:
var resultsByCustomer = query.GroupBy(x => x.Customer)
but this doesn't work, because it seems to group by object equality on the Customer class, not the customer id.
Is it possible to group by Customer Id, but have the whole customer object returned as the Key?
Go ahead and group them by the customer ID (with the ID as they Key), and then extract the customer from the first item in the group.
var resultsByCustomer =
from g in query.GroupBy(x => x.Customer.Id)
let customer = g.Select(x => x.Customer).FirstOrDefault()
select ...;

Find Minimum and Maximum of a column in LInq query result

I have an Linq query like this:
var result = from c in displayedEmployees select new[] { c.Name, c.Code, c.Rank.ToString(), c.Id.ToString(),c.Rank. };
If i want to select the min and max of any column for example Rank along with this like:
var result = from c in displayedEmployees select new[] { c.Name, c.Code, c.Rank.ToString(), c.Id.ToString(),min(c.Rank) ,max(c.Rank)};
how can I do this?
Select actually performs a transformation of every item (displayedEmployee), so ends up with the same number of items as you started with. Min and max are reductions, they reduce the list into a scalar.
After the "select" keyword is a function that only recieves the current item (c in your case). So there is no way to get the max there and you don't want every item in result to repeat the same maximum value.
You should compute the minimum and maximum separately.
After:
var result = from c in displayedEmployees select { c.Name, c.Code, c.Rank };
You could do something like this:
var min = result.Min(x => x.Rank);
var max = result.Max(x => x.Rank);
See more samples here (LINQ 101): http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

Filter list having two Tables join data in Entity Framework

I have two tables..
Student (StudentId,Name,FatherName)
Qualification (QualificationId,StudentId,DegreeName)
I have got data like this..
var myList = (from c in entities.Students
join q in entities.Qualifications on c.StudentId equals q.StudentId
select new {c.Name,c.FatherName,q.DegreeName}).ToList();
Now i want to filter myList more.. How can i do it, like..
var filteredList = myList.Select(c=> new Student
{
Name=c.Name,
FatherName=c.FatherName
//Degree=C.Degree
}).ToList();
The above Linq Query is not working if i want to get DegreeName also, My Question is how to further Filter myList.
Thanks.
var filteredList = myList.Where(i => i.FatherName == "Shahid").ToList();
Keep in mind since you called ToList() on the original query you are now filtering in memory. If you want to filter in the database then remove the ToList() on the first query and do it like this:
var myList = from c in entities.Students
join q in entities.Qualifications on c.StudentId equals q.StudentId
select new {
c.Name,
c.FatherName,
q.DegreeName
};
var filteredInDatabase = myList.Where(i => i.FatherName == "Shahid").ToList();

Linq and group by clause

I am curious what the x is for in a a linq group by clause: group x by ...
The x can be replaced by an 1:
var query = from box in c.Boxes
join item in c.Items on box equals item.Box
group 1 by new { BoxId = box.BoxId, item.ItemType.ItemTypeId } into g
select new { g.Key.BoxId, g.Key.ItemTypeId, Count = g.Count() };
Does anybody have a sample where the x (or wathever local variable you chose in the group by ) is really of some value?
I mean
var query2 = from box in c.Boxes
group box by box.BoxId into q
select q.Key;
can be replaced by
var query2 = from box in c.Boxes
group 1 by box.BoxId into q
select q.Key;
That's the expression that determines what will go in the output of the group by clause.
You are actually not inspecting the whole output, but only the Keys, which are the same in the examples above, because the grouping is done by the same thing (box.BoxId).
However, replace the last line:
select q.Key;
with
select q;
You will notice that:
the group 1 by ... query will return an IGrouping<int, int> which will have all values set to 1
the group box by ... query will return an IGrouping<int, Box>, which will have all the boxId keys and, for each of them, the corresponding Box objects with respect to the grouping criteria.
In group x by... the x is what gets aggregated.
So you could write something like
var childrenByAge = from child in class
group getName(child) by child.Age;
This gives you a grouping containing names of children for each age.
Here is a simple example where you can test the difference easily:
static void Main(string[] args)
{
var grouping = from c in "Hello World!"
group c by c; // Replace 'group c by' with 'group 1 by'
// and compare results
foreach (var group in grouping)
{
Console.Write("KEY: {0} VALUES :", group.Key);
foreach (var value in group)
Console.Write(" {0}", value);
Console.WriteLine();
}
Console.ReadKey();
}

Update class field in LINQ - is it possible?

I have 2 tables, and want to get records from 1 table and to "update" one of its fields from another table, and to pass final list of "Payment" objects somewhere. I cannot use anonymouse type, i need to get the list of proper typed objects.
There was a long way.
Got data:
var paymentsToShow = from p in paymentsRepository.Payments
join r in recordTypeRepository.RecordType
on p.RecordType equals r.Reference into p_r
where p.Customer == CustomerRef
from r in p_r.DefaultIfEmpty()
select new
{
Payment = p,
RecordType = r
};
var objList = paymentsToShow.ToList();
Change required field (basically, Payment.RecordTypeName is empty):
foreach (var obj in objList)
{
obj.Payment.RecordTypeName = obj.RecordType.Name;
}
Got list with correct type:
var paymentsList = from o in objList
select o.Payment;
Is there any way to get code shorter, to make required field update in the query or something else? I dont know where to look for.
I cannot change database.
You could do it like this:
var paymentsToShow = (from p in paymentsRepository.Payments
join r in recordTypeRepository.RecordType
on p.RecordType equals r.Reference into p_r
where p.Customer == CustomerRef
from r in p_r.DefaultIfEmpty()
select new
{
Payment = p,
RecordType = r
}).Select(x =>
{
x.Payment.RecordTypeName = x.RecordType.Name;
return x.Payment;
});
This will result in an IEnumerable<Payment>, so no anonymous type used.

Resources