score:1
Here is a suggestion where TimeAndCode.Code
is an enum
rather than a string
.
It will always order entries with indentical timespans in a repeated CO
, GO
, BT
pattern; meaning that if e.g. five entries with identical timespans has the following Code
selection: 2 x CO
, 1 x BT
, 2 x GO
, it will always order them as CO
, GO
, BT
, CO
, GO
(as opposed to CO
, GO
, CO
, GO
, BT
).
I achieve this by generating an OrderBy
property based on the timespan, an index (generated inside a nested group) and the numerical Code
value for each entry.
Using the following types:
public struct TimeAndCode
{
public TimeSpan Time { get; set; }
public Code Code { get; set; }
}
public enum Code
{
Undefined,
CO,
GO,
BT
}
we can write the following expression:
List<TimeAndCode> result = list
.GroupBy(entry => entry.Code)
.SelectMany(gr => gr
.GroupBy(entry => entry.Time)
.SelectMany(gr => gr.Select((entry, index) => (
OrderBy: entry.Time.ToString() + index + (int)entry.Code,
TimeAndCode: entry))))
.OrderBy(entry => entry.OrderBy)
.Select(entry => entry.TimeAndCode)
.ToList();
where list
is a List<TimeAndCode>
.
Using example input as follows:
List<TimeAndCode> list = new List<TimeAndCode>
{
new TimeAndCode { Time = new TimeSpan(09, 00, 00), Code = Code.GO },
new TimeAndCode { Time = new TimeSpan(13, 30, 00), Code = Code.BT },
new TimeAndCode { Time = new TimeSpan(09, 30, 00), Code = Code.GO },
new TimeAndCode { Time = new TimeSpan(09, 30, 00), Code = Code.GO },
new TimeAndCode { Time = new TimeSpan(13, 30, 00), Code = Code.GO },
new TimeAndCode { Time = new TimeSpan(08, 00, 00), Code = Code.CO },
new TimeAndCode { Time = new TimeSpan(09, 30, 00), Code = Code.BT },
new TimeAndCode { Time = new TimeSpan(12, 30, 00), Code = Code.CO },
new TimeAndCode { Time = new TimeSpan(09, 30, 00), Code = Code.CO },
new TimeAndCode { Time = new TimeSpan(12, 30, 00), Code = Code.GO },
new TimeAndCode { Time = new TimeSpan(13, 30, 00), Code = Code.CO },
new TimeAndCode { Time = new TimeSpan(13, 30, 00), Code = Code.CO },
new TimeAndCode { Time = new TimeSpan(09, 30, 00), Code = Code.CO },
new TimeAndCode { Time = new TimeSpan(13, 30, 00), Code = Code.GO },
};
, after applying the Linq expression, we can then print the result
foreach (var entry in result)
{
Console.WriteLine("Time: " + entry.Time + " Code: " + entry.Code);
}
and get the following output:
Time: 08:00:00 Code: CO
Time: 09:00:00 Code: GO
Time: 09:30:00 Code: CO
Time: 09:30:00 Code: GO
Time: 09:30:00 Code: BT
Time: 09:30:00 Code: CO
Time: 09:30:00 Code: GO
Time: 12:30:00 Code: CO
Time: 12:30:00 Code: GO
Time: 13:30:00 Code: CO
Time: 13:30:00 Code: GO
Time: 13:30:00 Code: BT
Time: 13:30:00 Code: CO
Time: 13:30:00 Code: GO
score:1
It's a variation of Astrid's:
var r = list.GroupBy(tc => tc)
.SelectMany(g => g.Select((tc, i) => (tc, i)))
.OrderBy(t => (t.tc.Time, t.i, t.tc.Code))
.Select(t => t.tc);
With the following precursor setup:
public record TimeAndCode(TimeSpan Time, Code Code);
public enum Code { CO, GO, BT }
...
var list = new List<TimeAndCode>
{
new (TimeSpan.FromHours(8), Code.CO),
new (TimeSpan.FromHours(9), Code.GO),
new (TimeSpan.FromHours(9.5), Code.CO),
new (TimeSpan.FromHours(9.5), Code.GO),
new (TimeSpan.FromHours(9.5), Code.GO),
new (TimeSpan.FromHours(9.5), Code.CO),
new (TimeSpan.FromHours(9.5), Code.BT),
new (TimeSpan.FromHours(12.5), Code.CO),
new (TimeSpan.FromHours(12.5), Code.GO),
new (TimeSpan.FromHours(13.5), Code.CO),
new (TimeSpan.FromHours(13.5), Code.BT),
new (TimeSpan.FromHours(13.5), Code.GO),
new (TimeSpan.FromHours(13.5), Code.CO),
new (TimeSpan.FromHours(13.5), Code.GO),
};
TimeAndCode is a record, which means it gains some useful properties for sorting and comparing. It can be simply grouped because it is automatically equal to another TimeAndCode with the same data
Grouping by the time and code results in a list-of-lists; the two 9:30 CO
s go in a list. Passing this to Select((tc,i)
means that i
is 0 for the first and 1 for the second etc.. All we do with this is promote it to a tuple of the tc
and the i
because we'll need them later, and we SelectMany to undo the GroupBy that allowed us to count the same Time/Code
We OrderBy another tuple; tuples sort by their values in order, so to order by 3 things a, b, and c, we can OrderBy a tuple of (a, b, c)
And all that is left to do at the end is select the tc
back to make a list of TimeAndCode, sorted something like what you want
Like Astrid's it also doesn't put the BT at the end for 9:30 - it goes in the middle, like 13:30's does.. But you haven't provided an explanation for why 9:30's BT is at the end...
Source: stackoverflow.com
Related Articles
- C# rearrange List by pattern
- List or Array of String Contain specific word in Html Source Code
- c# Linq or code to extract groups from a single list of source data
- Could not find an implementation of the query pattern for source type 'System.Data.Entity.DbSet'
- Rearrange a list based on given order in c#
- Generating the Shortest Regex Dynamically from a source List of Strings
- LINQ Source Code Available
- .NET 4 Code Contracts: "requires unproven: source != null"
- Avoid extra loop and could not find implementation of query pattern for source type int Select not found
- LINQ query returns old results when source list is re-initialized
- Copy a list of objects to another typed list in one line of code
- C# - Linq optimize code with List and Where clause
- Could not find an implementation of the query pattern for source type
- creating Linq to sqlite dbml from DbLinq source code
- Linq sub query when using a repository pattern with EF code first
- How can i copy data table records of different field name based on mapping list evaluating condition on source data table?
- how to find out existance of specific pattern in a list of integers by help of Linq. C#
- How to effectively select all values matching given pattern from a list of struct?
- Rearrange of a nested List with Linq
- Could not find an implementation of the query pattern for source type 'System.Data.Entity.DbSet` 'Where' not found
- Code to apply expression tree directly to List
- Search by zip code and filter list within specific radius?
- I can't get pagination to show up in every page on a GridView with a list as source
- Getting "Could not find an implementation of the query pattern for source type 'ExcelQueryable<T>'. " Error
- Accessing a List multiple times in same code block - Any better approach?
- Code practice to handle empty result set in Linq to custom list
- How to list all subdirectories with certain date pattern in c#
- Code First EF: While searching database table is it possible to retrieve list of items it has in DataModel?
- select from list which has same code
- Linq extension. Change property value in source list
- Convert a List of Anonymous type to a list of a specific Class type
- How do I use LINQ to group & project objects, based on a member dictionary key?
- Returning multiple fields with LINQ GroupBy on a datatable
- Will bad things happen to me if I name my arrays, collections, lists, enumerables, etc. just the plural of what they contain?
- Joined Linq query to DataTable and result to DataView
- Get value from XML through linq
- Why does LINQ take more time to execute than foreach?
- Unknown Select(?) of System Data Entity DbSet
- Filter linq list on property value
- Linq to Entities Remove without fetching
- How to find List has duplicate values in List<string>
- How to remove list element?
- how to replace each element (of struct type) with another element in an array using Linq?
- How to use group by and min statment of linq for one array?
- Dynamic "WHERE" like queries on memory objects
- Downcasting baseclass into derived generic type C#
- Automatically checking for NULL relationships with LINQ queries
- How to query XML with the same element and attribute name using linq
- Linq Query Group By and Selecting First Items
- Using LINQ on ObservableCollection with GroupBy and Sum aggregate