I am displaying a list of events by day from SQL database using the code:
IEnumerable<EventInstance> distinctDate = instances
.GroupBy(e => e.StartDate.Date)
.Select(group => group.First());
foreach (var instance in distinctDate)
{
// code to display here
}
What I am trying to do is divide them up by month on the page, so in between each month going down the page, i can put the Month Heading in a H3 tag
If you want one event for each day then grouped by month I think this is what you are looking for. Note you have to also group by year to avoid lumping dates from different years together. I also added a order by in there to make sure the events are in order by date.
var distinctDate = instances
.GroupBy(e => e.StartDate.Date)
.Select(grp => grp.First())
.OrderyBy(e => e.StartDate.Date)
.GroupBy(e => new { e.StartDate.Year, e.StartDate.Month });
Then you would do something like this
foreach(var monthGrouping in distinctDate)
{
var month = monthGrouping.Key.Month;
foreach(var singleDayEvent in monthGrouping)
{
var date = singleDayEvent.StartDate;
}
}
Related
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()
});
I am working on getting individuals who have not paid for the previous months
public ActionResult Arrears()
{
int month = DateTime.Now.Month;
int year = DateTime.Now.Year;
int i = 4;
do
{
var subscriber = db.Subscriptions
.Where(s => s.SubMonth == month && s.SubYear == year)
.Select(s => s.UserName).Distinct().ToList();
var alls = db.Members.Select(s => s.UserName).ToList();
var notsubs = alls.Except(subscriber).ToList();
List<Subscription> user = new List<Subscription>();
List<Subscription> querie = new List<Subscription>();
notsubs.ForEach(s => user.Add(new Subscription(s)));
month = month - 1;
i = i - 1;
return View(user);
} while (i != 0);
}
It gives me a list of the member who have not subscribed in the current month only and yet I want for the last 4 months
It gives me a list of the member who have not subscribed in the current month only and yet I want for the last 4 months
You have a return statement inside your loop. Since there is no condition around the return statement, you will exit the loop during the first iteration.
The quick fix is to declare the List user variable above the loop and to write the return statement below the loop.
That being said, users who have subscribed during at least one of the last 4 months but not another one will appear in the resulting list. If this is not intended, you might want to consider removing the loop entirely and grabbing all your subscriptions of the last 4 months in one go.
Also note that you will have a bug between January and March of each year because the year of the Subscription and your year variable won't match.
To avoid this, I would suggest not using the month and date as two separate fields but having a single field of type DateTime in your Subscription. You can then directly compare this field to DateTime.UtcNow.AddMonths(-4).
Edit:
With a DateTime field:
public ActionResult Arrears()
{
DateTime minDate = DateTime.UtcNow.AddMonths(-4);
var subscribers = db.Subscriptions
.Where(s => s.SubscriptionDate >= minDate)
.Select(s => s.UserName);
return View(
db.Members.Select(m => m.UserName)
.Where(u => subscribers.All(s => s != u))
.ToList());
}
With a Month and Year Field:
public ActionResult Arrears()
{
DateTime iterationDate = DateTime.UtcNow;
var subscribers =
db.Subscriptions.Where(
s => s.SubMonth == iterationDate.Month
&& s.SubYear == iterationDate.Year);
for(int i=0; i<3; i++)
{
iterationDate = iterationDate.AddMonth(-1);
subscribers = subscribers.Union(
db.Subscriptions.Where(
s => s.SubMonth == iterationDate.Month
&& s.SubYear == iterationDate.Year)
);
}
var subscriberNames = subscribers.Select(s => s.UserName).Distinct();
return View(
db.Members.Select(m => m.UserName)
.Where(u => subscriberNames.All(s => s != u))
.ToList());
}
Note that with the first solution you're looking at exactly the last 4 months (2019-03-10), while with the second solution you're looking at all subscriptions since 2019-03-01.
Note 2: these solutions will give you all members who have no subscriptions at all during the last 4 months. Is this what you need?
I have a list. I want to separate the list in pieces by (partionCountValue)variable. And I want to group data by a date value. And the data with the same date must be in the same pieces. I could not group the same date in the same group. How can I do this?
My example code:
var list = lstHareket.Select((x,i) => new { Index = i, Value = x})
.GroupBy(x => x.Index / partionCountValue)
.Select(x => x.Select(v => v.Value).ToList()
).ToList();
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() }));
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.