This question already has answers here:
Closed 2 years ago.
Is there an easy (linq?) way to split an int
array into new arrays based off unbroken numerical sequences? For example given this pseudo code:
[Fact]
public void ArraySpike()
{
var source = new[] {1, 2, 3, 7, 8, 9, 12, 13, 24};
var results = SplitArray(source);
Assert.True(results[0] == new[] {1, 2, 3});
Assert.True(results[1] == new[] {7, 8, 9});
Assert.True(results[2] == new[] {12, 13});
Assert.True(results[3] == new[] {24});
}
public int[][] SplitArray(int[] source)
{
return source.???
}
This can work with the linq extension Aggregate
. My seeding is not very elegant but that is easy enough to change. The results
variable will contain the array of arrays and they are actually of type List<T>
because that way they can be easily grown in the function where an array [] is always of fixed size.
This also assumes the source is already ordered and unique, if that is not the case add .OrderBy(x => x).Distinct()
var source = new[] { 1, 2, 3, 7, 8, 9, 12, 13, 24 };
var results = new List<List<int>>{new List<int>()};
var temp = source.Aggregate(results[0], (b, c) =>
{
if (b.Count > 0 && b.Last() != c - 1)
{
b = new List<int>();
results.Add(b);
}
b.Add(c);
return b;
});
I dug up this extension method from my personal collection:
public static IEnumerable<IEnumerable<T>> GroupConnected<T>(this IEnumerable<T> list, Func<T,T,bool> connectionCondition)
{
if (list == null)
{
yield break;
}
using (var enumerator = list.GetEnumerator())
{
T prev = default(T);
var temp = new List<T>();
while (enumerator.MoveNext())
{
T curr = enumerator.Current;
{
if(!prev.Equals(default(T)) && !connectionCondition(prev, curr))
{
yield return temp;
temp = new List<T>();
}
temp.Add(curr);
}
prev = curr;
}
yield return temp;
}
}
It solves the problem in a more general sense: split up a sequence in subsequences of elements that are "connected" somehow. It traverses the sequence and collects each element in a temporary list until the next item isn't "connected". It then returns the temporary list and begins a new one.
Your array elements are connected when they have a difference of 1
:
var results = source.GroupConnected((a,b) => b - a == 1);