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 Query
- 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
More Query from same tag
- Tuples - Only parameterless constructors and initializers are supported in LINQ to Entities
- order by how many matches in PredicateBuilder
- Linq to Entities doesn't return same value as foreach
- Cast List<object> to List<myclass> c#
- Cast to object from join
- Handling special character input for data selection
- Call function using Mongodb-CSharp Driver
- Linq join - group by - OrderByDescending query
- LINQ to Entities does not recognize the method 'System.String Format
- Where IN clause in LINQ
- Conditional Sum in LINQ
- Unit test IObservable<T> with ObserveOnDispatcher
- Separation of Concerns: Returning Projected Data between layers From a Linq Query
- What is LINQ equivalent of SQL’s "IN" keyword
- Entity Framework with Oracle using odp.net not taking parameters in linq query
- How do I deserialize DataTable Rows Collection into List<T>
- linq where clause using containsAll
- "Object reference not set to an instance of an object" error while trying to get the count
- Dynamic linq-to-nhibernate query problem
- How to fill a string with ordered elements via LINQ?
- Convert xml to CLR type using Linq
- Caching Method For Result String or Linq Query in Web Services C#
- Modify values before inserting through an EntityDataSource Object
- Linq, select values + - a value
- How to pass a variable in the query below
- method with optional parameter
- Getting error: 'System.Collections.Generic.IEnumerable<AnonymousType#1>' does not contain a definition for 'ToList'
- How do you left join using "date between" operator in linq?
- Join a list with an entity and get the average from the second table
- How do i merge these queries into 1