Split List into Sublists with LINQ
Try the following code.
public static List<List<T>> Split<T>(IList<T> source)
{
return source
.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / 3)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
}
The idea is to first group the elements by indexes. Dividing by three has the effect of grouping them into groups of 3. Then convert each group to a list and the IEnumerable
of List
to a List
of List
s
C# How to split a List in two using LINQ
You can do this in one statement by converting it into a Lookup table:
var splitTables = events.Tolookup(event => event.Closer_User_ID == null);
This will return a sequence of two elements, where every element is an IGrouping<bool, EventModel>
. The Key
says whether the sequence is the sequence with null Closer_User_Id, or not.
However this looks rather mystical. My advice would be to extend LINQ with a new function.
This function takes a sequence of any kind, and a predicate that divides the sequence into two groups: the group that matches the predicate and the group that doesn't match the predicate.
This way you can use the function to divide all kinds of IEnumerable
sequences into two sequences.
See Extension methods demystified
public static IEnumerable<IGrouping<bool, TSource>> Split<TSource>(
this IEnumerable<TSource> source,
Func<TSource,bool> predicate)
{
return source.ToLookup(predicate);
}
Usage:
IEnumerable<Person> persons = ...
// divide the persons into adults and non-adults:
var result = persons.Split(person => person.IsAdult);
Result has two elements: the one with Key true has all Adults.
Although usage has now become easier to read, you still have the problem that the complete sequence is processed, while in fact you might only want to use a few of the resulting items
Let's return an IEnumerable<KeyValuePair<bool, TSource>>
, where the Boolean value indicates whether the item matches or doesn't match:
public static IEnumerable<KeyValuePair<bool, TSource>> Audit<TSource>(
this IEnumerable<TSource> source,
Func<TSource,bool> predicate)
{
foreach (var sourceItem in source)
{
yield return new KeyValuePair<bool, TSource>(predicate(sourceItem, sourceItem));
}
}
Now you get a sequence, where every element says whether it matches or not. If you only need a few of them, the rest of the sequence is not processed:
IEnumerable<EventModel> eventModels = ...
EventModel firstOpenEvent = eventModels.Audit(event => event.Closer_User_ID == null)
.Where(splitEvent => splitEvent.Key)
.FirstOrDefault();
The where says that you only want those Audited items that passed auditing (key is true).
Because you only need the first element, the rest of the sequence is not audited anymore
linq: how to divide a list into two by the sum of the values and keeping the input order
You can use a for
-loop:
int minDelta = int.MaxValue;
var list1 = new List<ClassName>();
var list2 = new List<ClassName>();
for (int i = 0; i < list.Count - 1; i++)
{
int count = i + 1;
int sum1 = list.Take(count).Sum(x => x.Value);
int sum2 = list.Skip(count).Sum(x => x.Value);
int delta = Math.Abs(sum1 - sum2);
if (delta < minDelta)
{
minDelta = delta;
list1 = list.Take(count).ToList();
list2 = list.Skip(count).ToList();
}
}
Split two strings into List<string> and compare using Linq
Try splitting both strings and then use LINQs Intersect()
to get splits that are in both strings and Any()
to check whether there is such an intersection:
var first = "I like sand";
var second = "san dune";
var result = first.Split(' ').Intersect(second.Split(' ')).Any();
Split a List into several Lists based on criteria using LINQ
Although doable, this is an excellent example of what LINQ is not for. Check yourself.
Having
var myList = new List<int> { 100, 200, 300, 400, 200, 500, };
int maxSum = 600;
"Pure" LINQ (the power of Aggregate)
var result = myList.Aggregate(
new { Sum = 0, List = new List<List<int>>() },
(data, value) =>
{
int sum = data.Sum + value;
if (data.List.Count > 0 && sum <= maxSum)
data.List[data.List.Count - 1].Add(value);
else
data.List.Add(new List<int> { (sum = value) });
return new { Sum = sum, List = data.List };
},
data => data.List)
.ToList();
A normal (non LINQ) implementation of the above
var result = new List<List<int>>();
int sum = 0;
foreach (var value in myList)
{
if (result.Count > 0 && (sum += value) <= maxSum)
result[result.Count - 1].Add(value);
else
result.Add(new List<int> { (sum = value) });
}
For completeness (and some fun), a "Hackish" LINQ (the power of closures and C# operators)
int sum = 0, key = -1;
var result = myList.GroupBy(x => key >= 0 && (sum += x) <= maxSum ? key : ++key + (sum = x) * 0, (k, e) => e.ToList()).ToList();
Split a collection into `n` parts with LINQ?
A pure linq and the simplest solution is as shown below.
static class LinqExtensions
{
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int parts)
{
int i = 0;
var splits = from item in list
group item by i++ % parts into part
select part.AsEnumerable();
return splits;
}
}
Using LINQ to split items within a list
Use SelectMany to flatten results of splitting each name by :
names.SelectMany(n => n.Split(':'))
.Dump();
Related Topics
Copy Files With Authentication in C#
How to Dynamically Adjust Table Column Width in Rdlc Report
How to Submit Disabled Input in ASP.NET MVC
Itextsharp Pdfptable How to Make a Border Around Entire Table
Drawing a Triangle With Rounded Corners
Decrypt M3U8 Playlist Encrypted With Aes-128 Without Iv
Browser Back Button Navigates to Login Page When User Is Still Logged In
The Incoming Request Has Too Many Parameters. the Server Supports a Maximum of 2100 Parameters
Microsoft Azure: How to Create Sub Directory in a Blob Container
How to Get Url Referrer in ASP.NET Core MVC
Convert Byte Array to Wav File
How to Perform Join Between Multiple Tables in Linq Lambda
C# Download Big File from Server With Less Memory Consumption
Httpclient Post With Parameters in Body
Display Label Text With Line Breaks in C#