Convert to IEnumerable<DateTime> result of LINQ Query - c#

I have a linq Query
var tListOfDates = tList.GroupBy(g => g.dateOfSlot)
.Select(s => new {s.Key.Value });
dateOfSlot is a DateTime value
How can I convert tListOfDates to IEnumerable<DateTime>
I've tried top cast the result, but it doesn't work.

You should drop anonymous class new {s.Key.Value } (you don't want it but DateTime):
var tListOfDates = tList
.GroupBy(g => g.dateOfSlot)
.Select(s => s.Key.Value);
It seems that dateOfSlot is of type DateTime?, not DateTime since you put s.Key.Value, not s.Key; if my guess is right you can put it as
var tListOfDates = tList
.Where(item => item.dateOfSlot.HasValue)
.Select(item => item.dateOfSlot.Value)
.Distinct();

A proposition,you take all dates and get the unique date by Distinct
var tListOfDates = tList.Select(g => g.dateOfSlot).Distinct();

I Solved with
IEnumerable<DateTime> tListOfDates = tList.Where(w => w.dateOfSlot.HasValue).Select(g => g.dateOfSlot).Distinct().ToArray().Cast<DateTime>();
May be there is something more that needed and the query can be simplified.

So you have an object tlist, which implements IEnumerable<MySlot>. We don't know a lot of MySlot, yet we know that every MySlot object has a DateTime property DateOfSlot.
The first part of your LINQ statement groups all MySlots in your tlist into groups of MySlots where every MySlot in the group has equal DateOfSlot:
tList.GroupBy(mySlot => mySlot.dateOfSlot)
Every group has a Key which contains this common DateOfSlot. So the Key is d DateTime object
The second part projects every group into one element:
.Select(group => new {group.Key.Value });
group.Key is a DateTime. The problem is that a Datetime does not have a property Value. Are you sure that DateOfSlot is a DateTime?
It's not entirely certain what you want.
I have an IEnumerable<MySlot> in tList, and I want all used DateOfSlot values in this list
var allUsedDateOfSlotValues = tList.Select(mySlot => mySlot.DateOfSlot);
But now I have duplicates, I don't want duplicates!
var allDistinctUsedDateOfSlotValues = tList
.Select(mySlot => mySlot.DateOfSlot)
.Distinct();
This will have the same result as your code:
var result = tList.GroupBy(mySlot => mySlot.DateOfSlot)
// result: groups of mySlots with same DateOfSlot
.Select(group => group.Key)
// result: distinct values of DateOfSlot

Related

Casting Nhibernate result into IDictionary<string,int>

I am trying to convert the result of the query into IDictionary
Here string will contain orderId and the int will contain the TradedQuantity
The query below should join three objects Order, OrderRevision and OrderEvent.
1 Order can have many orderRevisions
1 OrderRevision can have many orderEvents
What the query is trying to do is to inner join three objects and get all order objects whose order id matches the list of orderids supplied to it. Then it does a group by based on orderId and gets the latest TradedQuantity from orderEvents object. LatestTradedQuantity will be the TradedQuantityFrom latest OrderEvent. For now the latest orderevent can be regarded as the one that has highest OrderEventId value.
OrderRevision revisionAlias = null;
Order orderAlias = null;
var query =
Session.QueryOver<OrderEvent>()
.JoinAlias(oe => oe.OrderRevision,() => revisionAlias)
.JoinAlias(oe => oe.OrderRevision.Order,() => orderAlias)
.Where(x => x.OrderRevision.Order.SourceSystem.Name.ToLower() == sourceSystem.ToLower())
.WhereRestrictionOn(x => x.OrderRevision.Order.Id).IsIn(orderIds.ToList())
.SelectList(list => list.SelectGroup(x => x.OrderRevision.Order.SourceOrderIdentifier)
.SelectMax(x => x.Id).Select(x => x.TradedQuantity))
.Select(x => new KeyValuePair<string, int?>(x.OrderRevision.Order.SourceOrderIdentifier, x.TradedQuantity)
);
As this query does not do what is supposed to. Could you please help and let me know how the result can be cast into IDictionary?
You have tagged your question with linq-to-nhibernate, so I guess using it instead of queryover would suit you. With Linq, use a sub-query for selecting the "max" order events ids for each order, then query them and project them to a dictionary.
using System.Linq;
using NHibernate.Linq;
...
var orderEventsIdsQuery = Session.Query<OrderEvent>()
.Where(oe => orderIds.Contains(oe.OrderRevision.Order.Id))
.GroupBy(oe => oe.OrderRevision.Order.SourceOrderIdentifier,
(soi, oes) => oes.Max(oe => oe.Id));
var result = Session.Query<OrderEvent>()
.Where(oe => orderEventsIdsQuery.Contains(oe.Id))
.ToDictionary(oe => oe.OrderRevision.Order.SourceOrderIdentifier,
oe => oe.TradedQuantity);
This should do the job. I do not use QueryOver and I will not try to give an answer for doing it with QueryOver.

find the original key of groupby in linq C#

var aaa = data.GroupBy(o => o.Date).Select(o => new { o }).ToList();
var bbb = aaa.Select(o => o.Key).ToList();
//There is a error of `Key`
Does that mean the Key is only allowed for the original List after GroupBy. Is it possible to obtain the Key for any Select after GroupBy?(Surely, we can storge the Key = o.Key in the Select )
Furthermore,
var aaa = data.GroupBy(o => o.Date).Select(o => o.ToList()}).ToList();
If we change aaa into two dimensional List, Is it possible to obtain the previous Key?
In your first linq expression, in the Select you are wrapping the IGrouping object that you got from the GroupBy with a new anonymous object.
So to get that Key property in your second line you should:
//Original:
var bbb = aaa.Select(o => o.Key).ToList();
//Change to:
var bbb = aaa.Select(o => o.o.Key).ToList();
For second question, if you want to get the Key in this case:
//Original:
var aaa = data.GroupBy(o => o.Date)
.Select(o => o.ToList()})
.ToList();
//Then you should:
var aaa = data.GroupBy(o => o.Date)
.Select(o => o.ToList()})
.Select(x => o.FirstOrDefault().Date)
.ToList();
Reason being is that:
You group your items by Date
First select you convert a IGrouping into a List<YourClass> but now you have an IEnumerable<List<YourClass>> where each record in the IEnumerable, all the inner items will have the same date
In second Select - take whichever item in the inner collections - and get the Date it is the same as getting the Key in the example before
To achieve what you actually what to get (grouping by the date and getting for each group the symbols):
var result = data.GroupBy(item => item.Date)
.Select(group => new { group.Key, Symbols = group.Select(item => item.Symbol).ToList() });
//Or using a different overload of the `GroupBy`:
var result = data.GroupBy(item => item.Date,
(key,group) => return new { Key = key, Symbols = group.Select(item => item.Symbol).ToList() });
Problem is your incorrect syntax. You crated an anonymous object, so you need to access the property with instance name. So you should be doing this.
var bbb = aaa.Select(o => o.o.Key).ToList();
if we change aaa into two dimensional List, Is it possible to obtain
the previous Key?
No, because you have groped values collection not the Key. So result will not contain Key.

c# - Linq Query to retrieve all objects with a max value

Currently I have a List of objects in which I need to find all occurrences that have the maximum value.
Currently my solution to this has been:
Foo maxFoo = list.OrderByDescending(foo => foo.A).First();
List<Foo> maxFoos = new List<Foo>();
foreach(Foo foo in list) {
if (foo.A.Equals(maxFoo.A)) {
maxFoos.Add(foo);
}
}
However I want to know if there is a way to do this in a single Linq expression.
All the resources I have read only refer to getting the max value for one object.
Note: For the time being, I want to know a solution which doesn't rely on MoreLinq
You can group by the property, then order the groups by key, and take the content of the first one, like this:
var res = list
.GroupBy(item => item.A)
.OrderByDescending(g => g.Key)
.First()
.ToList();
You could group by A, order the group, and get the elements in the first group, which corresponds to the elements with the max value of A:
list
.GroupBy(x => x.A)
.OrderByDescending(grp=> grp.Key)
.First()
.Select(x => x);
This works:
var maxFoos =
list
.OrderByDescending(foo => foo.A)
.GroupBy(foo => foo.A)
.Take(1)
.SelectMany(foo => foo)
.ToList();

LINQ projection combining date and list

I have a list of objects containg value and date of transaction.
DateTime Date { get ; set; }
double Value { get; set; }
I want to get the new grouped object which will contain date of transaction and list of values for this particular day.
I can retrieve both list and date but i dont know how to use projection to cast them into new object.
var res1 = ExpenseList.Where(p => p.Date == Convert.ToDateTime("01-12-2013"))
.Select(p => p.Value)
.ToList();
DateTime res2 = ExpenseList.Where(p => p.Date == Convert.ToDateTime("01-12-2013"))
.Select(p => p.Date)
.FirstOrDefault();
There might have been some confusion around I will post pictures to clarify
I have something like this in ExpenseList set of date and value
I want one Date and Collection of Values
To group all of the values for a particular day you'll want to use GroupBy
var groups = ExpenseList.GroupBy(expense => expense.Date,
expense => expense.Value);
ExpenseList.Where(p => p.Date == Convert.ToDateTime("01-12-2013"))
.Select(p => new MyObject {Date = p.Date, Value = p.Value})
.ToList();
Replace MyObject for the actual type you have defined.

C# - Failed to compare two elements in the array

This is my code:
var distinctDateValues = dt.AsEnumerable()
.Select(row => new
{
Date = DateTime.Parse(row.Field<string>("DAY"))
})
.Distinct()
.ToList();
distinctDateValues.Sort(); // getting error on this line
Values in distinctDateValues are:
The error i am getting is "Failed to compare two elements in the array."
Can anybody suggest me as what i am doing wrong here. I want to sort the values in date column of distinctDateValues.
Needless to create anonymous type, in your case the result distinctDateValues is a list of anonymous type, not a list of DateTime, you should get the sorted list of DateTime like below with OrderBy:
var distinctDateValues = dt.AsEnumerable()
.Select(row => row.Field<DateTime>("DAY"))
.Distinct()
.OrderBy(x => x)
.ToList();
Also, you should use built-in method Field<DateTime> instead of using one more step with DateTime.Parse
Just guessing here... your distinctDateValues don't know how to compare themselves... You would need to implement IComparable or something...
Try this:
var distinctDateValues = dt.AsEnumerable()
.Select(row => DateTime.Parse(row.Field<string>("DAY")))
.Distinct()
.ToList();
distinctDateValues.Sort(); // should not get any errors here...
If you really want to create an anonymous type (e.g., you are only showing us a small part of your code), try this:
var distinctDateValues = dt.AsEnumerable()
.Select(row => new
{
Date = DateTime.Parse(row.Field<string>("DAY"))
})
.Distinct()
.OrderBy(d => d.Date) // do the sorting here with linq
.ToList();

Categories

Resources