C# List querying and grouping - c#

I have this list:
OrderId ProductId DateTime
1 1 10.01.2012
1 2 09.01.2012
2 1 11.01.2012
3 1 12.01.2012
3 2 13.01.2012
I want to extract another another List from this that's only ProductId==1 and DateTime is 10.01.2012.
i.e. only productId==1 for every OrderId's.
Also I only want the least dateTime version of that item.
So for the above list, 10.01.2012 is the least dateTime where the productId==1.
Result Table;
OrderId ProductId DateTime
1 1 10.01.2012
how can I do this?

Here is a possible solution:
myList = myList.Where(x.ProductId == 1).OrderBy(x => x.DateTime);
That will order your new list by the DateTime value where the productId is equal to 1. If you want to get only the first one, you can use the .First() method of the list, e.g:
myCustomType = myList.Where(x => x.ProductId == 1).OrderBy(x => x.DateTime).First();

Related

Retrieve Last n Rows Starting From Last Row with Specified Value

I have a sample table below:
Id Action Qty
1 Start 3
2 Give 2
3 Take 1
...
X Start 8
X+1 Give 5
X+2 Take 3
Using EF, I would like to retrieve the last number of rows starting from last row where Action="Start".
With the sample table above, the result should be:
Id Action Qty
X Start 8
X+1 Give 5
X+2 Take 3
The following code will only work if there are 2 rows after the last Action="Start" row which is not always the case:
var result = db.Sample.OrderByDescending(x => x.Id).Take(3); // not always 3
You could group by, then find the max of Start, then get all Id's greater than or equal to max of Start. Actually, grouping is not necessary if your data is sorted.
var maxIdOfStart = collection
.OrderByDescending(x => x.Id)
.First(x => x.Action == "Start");
var lastNOfStart = collection
.Where(x => x.Id >= maxIdOfStart.Id);

Count Dates which a specific Customer does not have a Shop in it

Here is an example Data Table:
ID Amount Date
--------------------------
1 3.000 2016/1/1
2 4.000 2016/1/1
1 6.000 2017/1/1
1 3.000 2018/1/1
3 2.000 2019/1/1
I need to count Dates which a specific Customers does not have a Shop in it.
for example ID 2 does not have a shop in 2017/1/1 and 2018/1/1, so the count will be 2. and the count for customer ID 3 will be 3 because He does not have a shop in 2016/1/1 and 2017/1/1 and 2018/1/1
I think I should use grouping but do not know how to count which I want for a specific ID!
orders.GroupBy(x => x.Date)......???
Assuming you have list of objects:
// number of all different dates
var datesCount = list.Select(i => i.Date).Distinct().Count();
int customerId = 2;
//number of dates with customer shopping
var customerDatesCount = list.Where(i => i.ID == customerId).Select(i => i.Date).Distinct().Count();
var nonShoppingDatesCount = datesCount - customerDatesCount;
You need two steps here.
Get all distinct order dates
var allDates = orders.Select(o => o.Date).Distinct();
Find those dates which customer don't have. Except operation will do that
var missingDates = allDates.Except(orders.Where(o => o.ID == 2).Select(o => o.Date));
If you need just number of missing dates, then use missingDates.Count() or (better) use solution by #Roma

Select if criteria is met

Lets say I have a datatable with three columns: timestamp, curveID and price. I would like to give a time and then select for each day the timestamp, curveID and price but only if all curveIDs are present.
The problem is, not for every time all the data is present, so at 10:00:00 there might be only data for curveID 1 but nothing for ID =2, and so forth.
I thought I could do the following to select the first dataset where all curveIDs are there and time is greater or equal to my criteria:
dataSet.ReadXml(#"C:\temp\Prices.xml", XmlReadMode.InferTypedSchema);
ds = dataSet.Tables[0];
var dt = ds.Clone();
int criteria = 10;
var list = ds.AsEnumerable().Where(x => x.Field<DateTime>("Timestamp").Hour >= criteria)
.GroupBy(x => new{Date = x.Field<DateTime>("Timestamp").Date, Curve = x.Field<object>("CurveID")})
.First().ToList();
However, this returns multiple records on the same day (at different times) for the same curve ID.
I would like to return only a single record for each curveID on each day at a time close to the criteria time where all curveIDs are present.
For clarity, lets say I m looking for curveID 1 & 2, if at 10:00:00 on day 1 only curveID 1 is present but curveID 2 is missing I would need to check whether at 10:01:00 both are there, if yes I take for that day the two record sets from that time. This I would have to check for every day in the database
// criteria is your integer Hour representation
var criteria = 10;
// array of curveIds to look for
var curveIds = new int[] {1, 2};
var result =
// grouping by date first
ds.GroupBy(x => x.Field<DateTime>("Timestamp").Date,
(date, items) => new { date, items = items
// items with the same timestamp go to one group
.GroupBy(i => i.Field<DateTime>("Timestamp"), (datetime, timestampItems) => new { datetime, timestampItems })
// filter by criteria
.Where(dti => dti.datetime.Hour >= criteria)
// filter by curveIds
.Where(dti => curveIds.All(cid => dti.timestampItems.Any(tsi => tsi.Field<int>("curveID") == cid)))
.OrderBy(dti => dti.datetime)
.FirstOrDefault() });
In the end you will receive a "per day" result fitting all your mentioned requirements: occurs after some criteria, have all curveIds, be earliest one.
You may want to group by Date first and then by hour using something like
group thing by new {
firstThing = x.Field<DateTime>("TimeStamp").Date,
secondThing = x.Field<DateTime>("TimeStamp").Date.Hour,
}
My syntax is probably off by a little, but that should get you moving in the right direction

find records by criteria and select only one if they have some equal field (LINQ)

I have a class BaseEvent and it have the following fields:
Name, RecurrenceStart, RecurrenceEnd, SimillarId
For example we have a data in a table:
Name RecurrenceStart RecurrenceEnd SimillarId
Event1 2012-02-21 09:00:00.000 2012-02-28 11:30:00.000 1
Event1 2012-02-21 04:30:00.000 2012-02-28 07:00:00.000 1
Event2 2012-02-21 06:30:00.000 2012-02-29 09:00:00.000 2
And we have the following query:
var today = DateTime.Now;
return Database.BaseEvents.Where(e => e.RecurrenceStart.Value.Date <= today
&& e.RecurrenceEnd.Value.Date >= today).ToList();
The query return all 3 records(for current date). But the first two record is the same event.
I want that in the result will only two records: 3 and (1 or 2).
How can I do this?
Thanks.
P.S. I was introduce SimillarId for this purpose, but I don't know how to build a query with it or not.
P.S.2. Change question name if it necessery.
Use .Distinct() with an IEqualityComparer<BaseEvent> as argument which you have to implement first.
Try this:
var today = DateTime.Now;
return Database.BaseEvents.Where(e => e.RecurrenceStart.Value.Date <= today
&& e.RecurrenceEnd.Value.Date >= today)
.GroupBy(v => v.Name).Select(g => g.First()).ToList();

How to write the following group by and stripping time Linq query?

I have list like this-
Id Date
1 01/03/2011 14:15:23.320
1 01/03/2011 16:15:23.320
1 01/03/2011 18:15:23.320
1 01/04/2011 19:15:23.320
2 01/03/2011 14:15:23.320
2 01/03/2011 15:15:23.320
2 01/03/2011 18:15:23.320
2 01/05/2011 19:15:23.320
2 01/07/2011 20:15:23.320
My desired output is -
Id Date
1 01/03/2011
1 01/04/2011
2 01/03/2011
2 01/05/2011
2 01/07/2011
So how can I group by on the first list on id and take only the date part and achieve the results above in Linq ?
Try something like this:
var result = yourList.GroupBy(item =>
new {Id = item.Id, Date = item.Date.Date});
Basically, DateTime.Date strips the time information.
To loop through the result, you could do:
foreach(var grp in result)
{
Console.WriteLine("{0}: {1}", grp.Key.Id, grp.Key.Date);
}
It appears that you want to group on the date and id, so you want to pull those out into a structure that you can group on. It's when you create this key structure that you can format the date using the Date property to create the grouping correctly:
from item in list
group item by new { item.Id, Date = item.Date.Date } into g
select g
At that point, the keys in the grouping returned will give you the list you want.

Categories

Resources