-2

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.

Nick Farsi
  • 366
  • 4
  • 19
  • Why does this need to be LINQ? A simple for/foreach loop sounds perfectly reasonable. LINQ [doesn't look to be the best tool for this job](https://stackoverflow.com/questions/18146446/how-to-group-in-linq-based-on-previous-value). – gunr2171 Dec 26 '21 at 17:01

2 Answers2

1

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();

Fiddle

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
0

try this

void Main()
{
    
   var arrList= arr.GroupCollection<int>().ToArray();
    
    if (arrList.Count() < 3) Console.WriteLine("Error! Array is too short");
    
    arrList.Dump();
    
    var group1=arrList[0].ToArray();
    var group2=arrList[1].ToArray();
    var group3=arrList[2].ToArray();
     
}

extension

public static class Util
{
    public static IEnumerable<IEnumerable<T>> GroupCollection<T>(this IEnumerable<T> arr) where T:IComparable
    {
        var  arrList = new List<List<T>>();

        var prevItem = arr.First();
        var currList = new List<T>();

        foreach (var item in arr)
        {
            if (item.CompareTo(prevItem) < 0)
            {
                arrList.Add(currList);
                currList = new List<T>();
            }
            currList.Add(item);
            prevItem = item;
        }
        arrList.Add(currList);
        return arrList;
    }
}
Serge
  • 40,935
  • 4
  • 18
  • 45