If I have a list of booleans, how do I convert into into a list (or any other IEnnumerable<int>
) of integers where each integer represents the length of each string of booleans using LINQ?
For example {true, true, false, false, true, true, true}
would become {2, 3}
as the first run of true
s is 2 long, and the second is 3 long. Or must I go back to for and foreach loops?
I am not interested in the number of false values, they are only important because they separate runs of true values.
So {true, true, true, false, true, true, true, true, false, false, true, true, true}
would become {3, 4, 3}
Something like this:
public static class IEnumerableExt
{
public static IEnumerable<int> ConsecutiveTrues(this IEnumerable<bool> bools)
{
var flag=false;
int count=0;
foreach(var b in bools)
{
if (b)
{
count++;
} else if (flag)
{
yield return count;
count=0;
}
flag=b;
}
if (flag)
yield return count;
}
}
then used like:
void Main()
{
var bools=new bool[]{true, true, false, false, true, true, true};
var results=bools.ConsecutiveTrues();
}
Using a pure LINQ way (taken mostly from https://stackoverflow.com/a/27574266/856353):
var str = new bool[]{true, true, true, false, true, true, true, true, false, false, true, true, true};
// Retain a horrid mutable sequence which tracks consecutive characters
var sequence = 0;
var grps = str
.Zip((str.Concat(new bool[]{str.Last()})).Skip(1),
(prev, current) => new { prev, current })
.GroupBy(p => new {
Ch = p.prev,
Sequence = p.current == p.prev
? sequence
: sequence++})
.Where(l=>l.Key.Ch==true)
.Select(l=>l.Count());
There is no bad LINQ, just bad ideas:). It can be done with LINQ pretty nicely and still, one knows what it does.
Well, I hope so:).
List<bool> lst = new List<bool>() { true, true, true, false, true, true,
true, true, false, false, true, true,
true };
var bb =
lst
.Aggregate(new List<int>(), (acc, element) =>
{
if (element == true && acc.Count < 1) acc.Add(1);
else if (element == true && acc.Count > 0) acc[acc.Count - 1] = acc[acc.Count - 1]++;
else if(acc.Count > 0 && acc[acc.Count - 1] > 0) acc.Add(0);
return acc;
}, acc =>
{
if (acc.Count > 0 && acc[acc.Count - 1] == 0)
{
acc.RemoveAt(acc.Count - 1);
}
return acc;
});
//{3, 4, 3}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With