How can I split an IEnumerableString into groups of IEnumerablestring
var result = sequence.Select((s, i) => new { Value = s, Index = i })
.GroupBy(item => item.Index / 3, item => item.Value);
Note that this will return an IEnumerable<IGrouping<int,string>>
which will be functionally similar to what you want. However, if you strictly need to type it as IEnumerable<IEnumerable<string>>
(to pass to a method that expects it in C# 3.0 which doesn't support generics variance,) you should use Enumerable.Cast
:
var result = sequence.Select((s, i) => new { Value = s, Index = i })
.GroupBy(item => item.Index / 3, item => item.Value)
.Cast<IEnumerable<string>>();
Split an IEnumerable into multiple IEnumerables
Try this:
public static IEnumerable<IList<Couple>> Split(IEnumerable<Couple> couples)
{
using (var enumerator = couples.GetEnumerator())
{
if (!enumerator.MoveNext())
{
yield break;
}
var current = enumerator.Current;
var group = new List<Couple> { current };
while (enumerator.MoveNext())
{
var next = enumerator.Current;
if (current.Indicator.Equals(next.Indicator))
{
group.Add(next);
}
else
{
yield return group;
group = new List<Couple> { next };
}
current = next;
}
yield return group;
}
}
Example:
var couples = new List<Couple>
{
new Couple("a",false),
new Couple("b",false),
new Couple("c",true),
new Couple("d",false),
new Couple("e",false),
new Couple("f",true),
new Couple("g",true),
new Couple("h",true),
new Couple("i",false),
new Couple("j",true),
new Couple("k",true),
new Couple("l",false),
new Couple("m",false),
};
var groupNr = 1;
foreach (var couplesGroup in Split(couples))
{
Console.WriteLine($"List {groupNr++}: ");
foreach (var couple in couplesGroup)
{
Console.WriteLine($"{couple.Text, 10}, {couple.Indicator}");
}
Console.WriteLine();
}
How to split IEnumerablestring to groups by separator?
Try the algorithm below. This will add a group of words to the dictionary whenever it comes across an empty line.
List<string> input = new List<string>()
{
"1",
"wordOfGroup11",
"wordOfGroup12",
"wordOfGroup1N",
"\n",
"2",
"wordOfGroup21",
"wordOfGroup22",
"\n"
};
Dictionary<string, List<string>> result = new Dictionary<string, List<string>>();
string firstWordOfGroup = "";
List<string> allWordsInGroup = new List<string>();
foreach (string line in input)
{
if (int.TryParse(line, out int index) == true)
{
allWordsInGroup.Clear();
continue;
}
// I don't know what "EmptyLine" means
if (line == "\n" || line == Environment.NewLine || line == string.Empty)
{
result.Add(firstWordOfGroup, allWordsInGroup);
}
else
{
if (allWordsInGroup.Count == 0)
{
firstWordOfGroup = line;
}
allWordsInGroup.Add(line);
}
}
Also note that if your groups can have the same first word (e.g. both starting with "WordOfGroup1" then you should use a List<KeyValuePair<string, List<string>>>
because the dictionary does not store duplicate keys.
Split an IEnumerableT into fixed-sized chunks (return an IEnumerableIEnumerableT where the inner sequences are of fixed length)
You could try to implement Batch method mentioned above on your own like this:
static class MyLinqExtensions
{
public static IEnumerable<IEnumerable<T>> Batch<T>(
this IEnumerable<T> source, int batchSize)
{
using (var enumerator = source.GetEnumerator())
while (enumerator.MoveNext())
yield return YieldBatchElements(enumerator, batchSize - 1);
}
private static IEnumerable<T> YieldBatchElements<T>(
IEnumerator<T> source, int batchSize)
{
yield return source.Current;
for (int i = 0; i < batchSize && source.MoveNext(); i++)
yield return source.Current;
}
}
I've grabbed this code from http://blogs.msdn.com/b/pfxteam/archive/2012/11/16/plinq-and-int32-maxvalue.aspx.
UPDATE: Please note, that this implementation not only lazily evaluates batches but also items inside batches, which means it will only produce correct results when batch is enumerated only after all previous batches were enumerated. For example:
public static void Main(string[] args)
{
var xs = Enumerable.Range(1, 20);
Print(xs.Batch(5).Skip(1)); // should skip first batch with 5 elements
}
public static void Print<T>(IEnumerable<IEnumerable<T>> batches)
{
foreach (var batch in batches)
{
Console.WriteLine($"[{string.Join(", ", batch)}]");
}
}
will output:
[2, 3, 4, 5, 6] //only first element is skipped.
[7, 8, 9, 10, 11]
[12, 13, 14, 15, 16]
[17, 18, 19, 20]
So, if you use case assumes batching when batches are sequentially evaluated, then lazy solution above will work, otherwise if you can't guarantee strictly sequential batch processing (e.g. when you want to process batches in parallel), you will probably need a solution which eagerly enumerates batch content, similar to one mentioned in the question above or in the MoreLINQ
Splitting an IEnumerable into two
Here is one simple method. Note that ToLookup
eagerly evaluates the input sequence.
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6 };
var lookup = list.ToLookup(num => num % 2 == 0);
IEnumerable<int> trueList = lookup[true];
IEnumerable<int> falseList = lookup[false];
You can use GroupBy
to get lazy evaluation of the input sequence, but it's not quite as pretty:
var groups = list.GroupBy(num => num % 2 == 0);
IEnumerable<int> trueList = groups.Where(group => group.Key).FirstOrDefault();
IEnumerable<int> falseList = groups.Where(group => !group.Key).FirstOrDefault();
Group IEnumerable into a string
Linq has a nice group by statement:
var emailGroup = emailList.GroupBy(e => e.alertCategory);
Then you can loop through each grouping and do whatever you want:
foreach(var grouping in emailGroup)
{
//do whatever you want here.
//note grouping will access the list of grouped items, grouping.Key will show the grouped by field
}
Edit:
To retrieve a group after you have grouped them, just use Where
for more than one or First
for just one:
var group = emailGroup.First(g => g.Key == "name you are looking for");
or
var groups = emailGroup.Where(g => listOfWantedKeys.Contains(g.Key));
this is a lot more efficient than looping through every time you need to find something.
Split a string into groups
Consider the following code...
string message = "0123456789";//10char string
//string message = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";//161char string
int parts = (message.Length/ 153) + (message.Length % 153 > 0 ? 1 : 0);
for (int x = 1; x <= parts; x++)
{
Console.WriteLine("this Msg Part: " + x.ToString());
Console.WriteLine("this Msg Part Text:" + message.Substring( (x-1)* 153, message.Length < ((x-1)* 153 + 153) ? message.Length - (x-1)* 153 : 153));
Console.WriteLine("Total Msg Parts: " + parts.ToString());
}
Good Luck!
Divide a large IEnumerable into smaller IEnumerable of a fix amount of item
Try something like this:
var result = items.Select((value, index) => new { Index = index, Value = value})
.GroupBy(x => x.Index / 5)
.Select(g => g.Select(x => x.Value).ToList())
.ToList();
It works by partitioning the items into groups based on their index in the original list.
C# LINQ split complex joined string data to a List of objects
Normal enumerable.Zip
var result = someObject_source.Model.Split(Delimeter_main)
.Zip(someObject_source.Color.Split(Delimeter_main), (x, y) => new { x, y })
.Zip(someObject_source.Size.Split(Delimeter_main), (zip1, z) =>
{
var secondSplit = z.Split(Delimeter_inner);
return new SomeObject_target
{
Model = zip1.x,
Color = zip1.y,
Size = secondSplit[0],
Quantity = double.TryParse(secondSplit[1], out double _quantity) ? _quantity : 1,
Nett = double.TryParse(secondSplit[2], out double _nett) ? _nett : 1,
};
});
Extention Method Zip on 3 collection
A little more readable, without the annonymous object wraper for the first Zip result.
var results = someObject_source.Model.Split(Delimeter_main)
.ZipThree(
someObject_source.Color.Split(Delimeter_main),
someObject_source.Size.Split(Delimeter_main),
(x, y, z) => {
var secondSplit = z.Split(Delimeter_inner);
return new SomeObject_target
{
Model = x,
Color = y,
Size = secondSplit[0],
Quantity = double.TryParse(secondSplit[1], out double _quantity) ? _quantity : 1,
Nett = double.TryParse(secondSplit[2], out double _nett) ? _nett : 1,
};
}
);
Related Topics
Is There an Exponent Operator in C#
Determine Number of Pages in a PDF File
How to Set/Change/Remove Focus Style on a Button in C#
..The Underlying Connection Was Closed: an Unexpected Error Occurred on a Receive
Will Using Linq to SQL Help Prevent SQL Injection
How to Set Read Permission on the Private Key File of X.509 Certificate from .Net
How to Read Image Pixels' Values as Rgb into 2D Array
Can You Compile C# So It Doesn't Need the .Net Framework at Runtime
Async/Await Keywords Not Available in .Net 4.0
How to Drag a Usercontrol Inside a Canvas
Closing a File After File.Create
How to Recognize If a String Contains Unicode Chars
Exporting Datagridview to CSV File
What's the Difference Between Double Quotes and Single Quote in C#
Creating an Mvvm Friendly Dialog Strategy