Order a list of string by quantity - c#

I have a list of string that i want to order by quantity. The List contain a list of Order-CreationDate with datetime values. I'm converting this values to strings as as i will need that for later.
My current output is a list of CreationDate that looks like this.
2014-04-05
2014-04-05
2014-04-05
2014-04-05
2014-04-06
2014-04-06
2014-04-06
...
I get a list of dates as expected but i want to group number of dates by the date. This mean i need another variable with number of total orders. Ive tried creating a new variable, using a for loop and linq queries but not getting the results I want.
How can I get number of orders by CreationDate? I need to count total number of orders by CreationDate but I can't find a way to do this.
The expected output would be:
2014-04-05 4 - representing 4 orders that date
2014-04-06 3 - representing 3 orders that date.
This what my code looks like:
List<string> TotalOrdersPaid = new List<string>();
foreach (var order in orders)
{
if (order.PaymentStatus == PaymentStatus.Paid)
{
string Created = order.CreatedOnUtc.Date.ToString("yyyy-MM-dd");
order.CreatedOnUtc = DateTime.ParseExact(Created, "yyyy-MM-dd", CultureInfo.InvariantCulture);
TotalOrdersPaid.Add(Created);
}
}
Eg TotalOrdersPaid should contain a list with number of orders by CreationDate.
What is a good way to achieve this?
Thanks

basically, you just need a group by and and ordering.
var result = orders//add any where clause needed
.GroupBy(m => m)
.Select(m => new {
cnt = m.Count(),
date = m.Key
})
.OrderByDescending(m => m.cnt);
Of course, you can add any DateTime.Parse / ParseExact in the Select, and / or project to a corresponding class.

To group the orders by date, take following LinQ lambda expression:
var grouped = orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc);
Now, all paid orders are grouped by date. To count the orders per date, select the key which is the date, and the Count() will count all orders for that date.
var counted = grouped.Select(s => new { Date = s.Key, Count = s.Count() });
Edit:
In one statement:
var result = orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc)
.Select(s => new { Date = s.Key, Count = s.Count() });
Based on your list of dates, the output will look like:
Date Count
5/04/2014 4
6/04/2014 3
Update:
If you want to put more properties in the anonymous type that will be returned from the Select() method, sumply just add them. If, for example, you want the date, the count and the list of orders for that date, use following line of code:
var result = orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc)
.Select(s => new
{
Date = s.Key,
Count = s.Count(),
Items = s.ToList()
});
Now you can do following:
foreach(var orderGroup in result)
{
Console.WriteLine(String.Format("Number of orders for {0}: {1}", orderGroup.Date, orderGroup.Count));
foreach(var order in orderGroup.Items)
{
Console.WriteLine(order.Name);
}
}
This will loop over all grouped items and display a sentence like:
Number of orders for 5/04/2014: 4
And then it will display the name of each order for that date (if your order has a property Name). Hope this clears everything out.

Related

LINQ Query for Unsanitized Data

I have a List<MyData> where MyData contains a Location field.
This field is a string, and is normally in "City, State" format but sometimes will come in as "Unknown".
There is another field, DateField.
I need to return a list of MyData objects grouped by the year in DateField, grouped by the state portion of Location, if that exists. If it comes in as "Unknown" then I need to ignore that.
My thoughts are use RemoveAll() on the List<> where (r => r.Location.Split(",").Length == 0), or if it doesn't include a comma at all.
Then I will have sanitized data.
That leaves me with two questions:
Is this the correct approach, or can I just handle it all with one LINQ query?
What should this LINQ query look like? I am looking state totals by a year specific year, which is passed into the API as an int.
I hope that comes across clear. Thanks.
If I understood you correctly, you can try to do the following. Filter the data with known Location first, then group it by two keys, year from DateField and State, and finally select a result
var data = new List<MyData>();
var result = data.Where(l => l.Location != "Unknown")
.GroupBy(d => new { d.DateField.Year, State = d.Location.Split(",").LastOrDefault() })
.Select(g => new
{
g.Key.Year,
g.Key.State,
Total = g.Count()
});
This query removes an state with unkonwn and also group on year of datefield ans state part of location
var mydata = new List<MyData>();
mydata.Where(x => x.Location != "Unknown")
.GroupBy(x => new { x.DateField.Date.Year, State =
x.Location.Split(',').LastOrDefault() })
.Select(x => new {
Year = x.Key.Year,
Count = x.Count()
});

Grouping by list of dates and summing the sales

I have an situation where I have defined a class like following:
class Item
{
List<DateTime> _TransactonDatesPast30Days = new List<DateTime>();
}
So the situation can be like following:
I have 25 transaction dates in the list...
Next item:
40 transaction dates
So now I have a List of items with all these parameters like following:
List<Item> _items = new List<Item>();
Now I need to group by the list within a list to get number of sales per day in final list...
For example:
12th of December occured 14 times in all List and now it's count is 14 , which will represent the number of sales made for that date...
In normal circumstances I would group them by like this:
ViewBag.LineGraph = lista
.GroupBy(l => l.TrasnactionDate)
.Select(cl => new Item
{
TrasnactionDate = cl.Key.TrasnactionDate.Date,
SaleNumber = cl.Count(c => cl.Key)
})
.OrderBy(x => x.TrasnactionDate)
.Where(x=>x.SaleNumber>0)
.ToList();
But it confuses me when I have list within a list that I need to group by, I have no ideas what to do now here when I have a list within a list that needs to grouped by the date...
// This wasn't grouping I guess
var result = _items.Select(x => x._TransactonDatesPast30Days).GroupBy(y => y).Select(x => new Item {_TransactonDatesPast30Days = x.Key ,Salesnumber = x.Count()});
Take this Solution: Update 2
var resultt2 = _items.Select(x => x._TransactonDatesPast30Days).
Select(r => r.GroupBy(x => x).Select(l => new Item { _TransactonDatesPast30Days = new List<DateTime>{l.Key}, Salesnumber = l.Count() }));

selecting a single item from grouped linq query based on a condition

I am struggling with a grouping linq query
I have this:
DateTime dateFrom = new Date(2014,8,2);
var GroupedPrices = Prices.Where(p => p.ArrivalDateFrom <= dateFrom
&&
p.ArrivalDateTo > dateFrom)
.GroupBy(p => p.ItemID);
I am trying to get to a single price of each ID - eg. in/from each group, based on the newest ValidFrom date of that price.
I have started by grouping them by their ItemID's (not the individual price record id's) but am struggling in working out how to grab just a single one based on that newest ValidFrom date. I thought I could order them before grouping, but wasn't sure that would stick after the grouping was done.. ie
expecting it will use a Max(x=>x.ValidFrom) type thing or OrderByDescending(x=>x.ValidFrom).First() but cant work that out
any help much appreciated
thanks
I think you just need to select what you want, at the end, like so:
DateTime dateFrom = new Date(2014,8,2);
var GroupedPrices = Prices
.Where(p => p.ArrivalDateFrom <= dateFrom && p.ArrivalDateTo > dateFrom)
.GroupBy(p => p.ItemID)
.Select(g => new{ ItemId = g.Key, NewestPrice = g.OrderByDescending(p => p.ValidFrom).First() });

Get sum of the value from list using linq?

I am trying to get the sum of the value from list of list using linq ?my data is as below code
List<List<string>> allData = new List<List<string>>();
using (StreamReader reader = new StreamReader(path))
{
while (!reader.EndOfStream)
{
List<string> dataList;
dataList = reader.ReadLine().Split('|').ToList();
allData.Add(dataList);
}
}
which gives me data in allData as below
allData-->[0]-->[0]-'name1'
[1]-'sub'
[2]-'12'
[1]-->[0]-'name2'
[1]-'sub'
[2]-'15'
[2]-->[0]-'name1'
[1]-'sub2'
[2]-'15'
//and so on ....
i have applied group by that gives me grouping by the name but i am not able to figure out how to get the sum of the marks for each name ?
var grouped = allData.GroupBy(x => x[0]);
after this i get all matching name grouped into one but now how to get sum of the marks for that group ? any help would be great ?
Output should be name1=27 and name2=15 and so on.
Not sure if you want to get the sum of every group or the total. If it's the total then this should do the trick
var sum = allData.Sum(x => Int32.Parse(x[2]));
If it's per key then try the following
var all = allData
.GroupBy(x => x[0])
.Select(x => x.Sum(y => Int32.Parse(y[2]));
var grouped = allData.GroupBy(x => x[0])
.Select(g => new
{
Name = g.Key,
Sum = g.Sum(x => int.Parse(x[2]))
});
It will return an anonymous type instance for each group, with two properties: Name with your grouping key and Sum with sum of marks.
Sticking as much as possible to the LINQ query language:
var grouped = from d in allData
group d by i[0] into g
select new
{
Name = g.Key,
Sum = g.Sum(i => int.Parse(i[2]))
};
This will give you parallel List with each name and the count of how many times each name occurs.
var names = grouped.Select(s => s.Key).ToList();
var nameCount = grouped.Select(s => s.Count()).ToList();
Also... you may want to add this when assigning alldata to grouped. I use this to get a List from greatest to least amount of occurrences.
var grouped = allData.GroupBy(x => x[0]).OrderByDescending(i => i.Count());

Linq to select latest records

I have the data structure
For each item there is a record of it's price on a certain date in each currency. I need to create a query that returns the most current price for each currency.
This query works, but returns multiple Amounts for currency ID 1. It should only return 3 records, 7,8 and 9 as these represent the most up to date prices in all currencies for this item.
var q = (from c in db.tblStoreItemPrices where c.ItemID == ID select new { c.CurrencyID, c.Amount });
Please ignore all ordering and assume that records are randomly ordered.
This should work:
db.tblStoreItemPrices
.Where(c => c.ItemID == ID)
.GroupBy(c => c.CurrencyID)
.Select(g => g.OrderByDescending(c => c.Date).First())
.Select(c => new { c.CurrencyID, c.Amount });
Explanation:
Select rows for the specific ItemID
Group by CurrencyID
From within each currency group select the row that has the most recent date (leaving one row for for each CurrencyID in the result set)
Pull out the information you want from these rows

Categories

Resources