Given:
var arr = new int[] {
10, 20, 30,
10, 20, 30, 40, 50,
10, 20
};
Wanted:
var group1 = new int [] { 10, 20, 30 };
var group2 = new int [] { 10, 20, 30, 40, 50 };
var group3 = new int [] { 10, 20 };
Need to group by value => when next element's value is lower than the previous one, create new group. Would appreciate LINQ-based solution.
CodePudding user response:
Technically, you can put something like this:
int prior = int.MinValue;
int group = 0;
var result = arr
.GroupBy(item => {
if (item < prior)
group = 1;
prior = item;
return group;
});
but if you don't insist on IGrouping<int, int>
and agree with IEnumerable<int[]>
, foreach
looks better (let's generalize the solution):
public static partial class EnumerableExtensions {
public static IEnumerable<T[]> GroupByAsc<T>(this IEnumerable<T> source,
Comparer<T> comparer = null) {
if (source is null)
throw new ArgumentNullException(nameof(source));
if ((comparer ??= Comparer<T>.Default) is null)
throw new ArgumentNullException(nameof(comparer),
$"Type {typeof(T).Name} doesn't have default comparer");
List<T> list = new List<T>();
foreach (var item in source)
if (list.Count > 0 && comparer.Compare(list[list.Count - 1], item) <= 0)
list.Add(item);
else {
if (list.Count > 0)
yield return list.ToArray();
list.Clear();
list.Add(item);
}
if (list.Count > 0)
yield return list.ToArray();
}
}
Usage:
var result = arr
.GroupByAsc();
CodePudding user response:
try this
void Main()
{
var arrList= GroupCollection(arr);
if (arrList.Count() < 3) Console.WriteLine("Error! Array is too short");
var group1=arrList[0].ToArray();
var group2=arrList[1].ToArray();
var group3=arrList[2].ToArray();
}
public static List<List<int>> GroupCollection(int[] arr)
{
List<List<int>> arrList = new List<List<int>>();
var prevItem = arr[0];
var currList = new List<int>();
foreach (var item in arr)
{
if (prevItem > item)
{
arrList.Add(currList);
currList = new List<int>();
}
currList.Add(item);
prevItem = item;
}
arrList.Add(currList);
return arrList;
}