Groupby list within the list using LINQ - c#

I have two classes:
class Customer
{
public string Name { get; set; }
public string ZipCode { get; set; }
public List<Order> OrderList { get; set; }
}
class Order
{
public string OrderNumber { get; set; }
}
Using LINQ, i want to get list of Orders group by ZipCode. If Zipcode "12121" has 10 customers and each has 2 orders then it should return me only one Zipcode with the list of 20 orders.
I am trying to do it like this but not able to figure out whats wrong
var orders = br.CustOrderList
.Select(r => new
{
r.ZipCode,
r.Name,
r.OrderList
})
.GroupBy(x => new { x.ZipCode, x.OrderList});
Any help please?

This should do what you want:
var orders = br.CustOrderList
.GroupBy(x => x.ZipCode)
.Select(g => new
{
ZipCode = g.Key,
Orders = g.SelectMany(x => x.OrderList)
});

var orders = br.CustOrderList
.Select(r => new
{
r.ZipCode,
r.Name,
r.OrderList
})
.GroupBy(x => x.ZipCode);
You just want to group by the ZipCode so just group by that
Ah yea just try
var order = br.CustOrderList
.GroupBy(x = x.ZipCode);
No need to select new items out of the list

Related

Get groups of elements from name inside of list C#

I have a List of :
public class GT
{
public string ActivityName { get; set; }
public int Seconds { get; set; }
}
And the ActivityName could repeat through the iteration and what I want to do is, regroup all the items that have the same name and calculate the average of seconds of these specifics items. I tried to use Distinct but it didn't group them.
You should use GroupBy instead of Distinct:
List<GT> list = /*...*/;
var query = list.GroupBy(x => x.ActivityName, (k,g) => new { ActivityName = k, AverageTimeInSeconds = g.Average(x => x.Seconds) });
var groups = items.GroupBy(p => p.ActivityName)
.Select(g => new
{
ActivityName = g.Key,
Average = g.Average(t => t.Seconds)
}).ToList();

Linq GroupBy with sort, take first, and return a list

I'm stuck on a Linq-to-SQL query. I have a table of items, with multiple items per user. I want to get the list of all the latest items per user. This is what I have:
var TheList = (from t in MyDataContext.TheTable
where t.SomeDate > DateTime.UtcNow.AddMonths(-3)
group t by t.UserID into TheUserGroups
from g in TheGroups
orderby g.SomeDate descending
select new SomeObject()
{
TheUserID = g.UserID,
.....
}).ToList();
The problem is that it's returning all the items of every user instead of the most recent element per user. What do I need to change to get the expected result?
Try following :
var TheList = (from t in MyDataContext.TheTable
where t.SomeDate > DateTime.UtcNow.AddMonths(-3)
orderby g.SomeDate descending
select new SomeObject()
{
TheUserID = g.UserID,
})
.GroupBy(x => x.TheUserID)
.Select(x => x.FirstOrDefault())
.ToList();
If I understood you correctly:
public class Order
{
public int OrderId { get; set; }
public int UserId { get; set; }
public DateTime Date { get; set; }
public string ItemName { get; set; }
}
table.Where(o => o.Date < DateTime.UtcNow.AddMonths(-3))
.GroupBy(o => o.UserId)
.Select(g => new { UserId = g.Key, LastOrder = g.OrderByDescending(o => o.Date).FirstOrDefault() })
.ToList();

LINQ to Entities, Where Any In

How to write 'Where Any In' in LINQ to Entity?
Here is my model :
class Chair
{
public int Id { get; set; }
public int TableId { get; set; }
public Table Table { get; set; }
}
class Table
{
public int Id { get; set; }
public ICollection<Chair> Chairs { get; set; }
public ICollection<Category> Categories { get; set; }
public Table()
{
Chairs = new List<Chair>();
Categories = new List<Category>();
}
}
class Category
{
public int Id { get; set; }
public ICollection<Table> Tables { get; set; }
}
I also got a simple list of Category :
List<Category> myCategories = new List<Category>(c,d,e);
I want to get only that Chairs that belongs to Table that got one of the Category from myCategories List. Thats what im trying to do :
var result =
ctx.Chairs.Where(x => x.Table.Categories.Any(y => myCategories.Any(z => z.Id == y.Id))).ToList();
I think its ok but what i get is error :
"Unable to create a constant value of type 'ConsoleApplication1.Category'. Only primitive types or enumeration types are supported in this context"
Try to compare with in-memory categories Ids collection, instead of categories collection.
var myCategoriesIds = myCategories.Select(c => c.Id).ToArray();
var result =
context.Chairs
.Where(
x => x.Table.Categories.Any(
y => myCategoriesIds.Contains(y.Id)))
.ToList();
this is because ctx.Chairs is a collection that is in database, you should retrieve that collection first in order to compare it with in-memory data:
var result = ctx
.Chairs
.AsEnumerable() // retrieve data
.Where(x =>
x.Table.Categories.Any(y =>
myCategories.Any(z => z.Id == y.Id)))
.ToList();
EDIT: that wouldn't be the correct thing to do if you have a lot of entities on database, what you can do is to split it into two queries:
var tables = ctx.Tables
.Where(x =>
x.Categories.Any(y =>
myCategories.Any(z => z.Id == y.Id)));
var result = ctx.Chairs
.Where(x =>
tables.Any(t=> t.Id == x.TableId))
.ToList();
You can select Ids from myCategories and use it last statement.
var CategoryIds = myCategories.Select(ct => ct.Id);
var result = ctx.Chairs.Where(x => x.Table.Categories.Any(y => CategoryIds.Any(z => z == y.Id))).ToList();

LINQ query for retrieving data from list

I have List collection of Message objects.
public class Message
{
public int Id { get; set; }
public string Body { get; set; }
public string Sender { get; set; }
public DateTime Timestamp { get; set; }
}
I want to get only one message with most recent Timestamp for each sender. How do I do it using LINQ?
You need to group by Sender and then get the Max Timestamp from each group like:
var query = list.GroupBy(r => r.Sender)
.Select(grp => new
{
Sender = grp.Key,
RecentTimeStamp = grp.Max(r => r.Timestamp)
});
Or you can sort the TimeStamp in group by descending order and get the first element like:
var query = list.GroupBy(r => r.Sender)
.Select(grp => new
{
Sender = grp.Key,
RecentTimeStamp = grp.OrderByDescending(r => r.Timestamp).FirstOrDefault()
});
var q = from n in table
group n by n.Senderinto g
select g.OrderByDescending(t=>t.Timestamp).FirstOrDefault();

Merge Duplicate list entries into one and display quantity in C#

I have a list as below.
List<Product> productList = new List<Product>();
And the Product class looks as follows.
public class Product
{
public int ID { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
}
Now if the user inserts duplicate list entries identified by ID, how will I be able to merge it as follows
Product Name Qty
Coke 2
Pepsi 7
You could use LINQ to build a new set of products:
var results = productList
.GroupBy(p => p.ID)
.Select(g => new Product { ID = g.Key, ProductName = g.First().ProductName, Quantity = g.Sum(i => i.Quantity) })
.ToList();
If you just need the product names and Quantities, you can use:
var results = productList
.GroupBy(p => p.ProductName)
.Select(g => new { ProductName = g.Key, Quantity = g.Sum() });
foreach(var product in results)
{
Console.WriteLine("{0} {1}", product.ProductName, product.Quantity);
}
var result = productList.GroupBy(p => p.ID)
.Select(g => new Product {
ProductName = g.First().ProductName,
Quantity = g.Sum(p => p.Quantity) });

Categories