Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split a list into multiple lists at increasing sequence broken

Tags:

I've a List of int and I want to create multiple List after splitting the original list when a lower or same number is found. Numbers are not in sorted order.

 List<int> data = new List<int> { 1, 2, 1, 2, 3, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 6 };

I want the result to be as following lists:

 { 1, 2 }
 { 1, 2, 3 }
 { 3 }
 { 1, 2, 3, 4 }
 { 1, 2, 3, 4, 5, 6 }

Currently, I'm using following linq to do this but not helping me out:

List<int> data = new List<int> { 1, 2, 1, 2, 3, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 6 };
List<List<int>> resultLists = new List<List<int>>();
var res = data.Where((p, i) =>
{
    int count = 0;
    resultLists.Add(new List<int>());
    if (p < data[(i + 1) >= data.Count ? i - 1 : i + 1])
    {
        resultLists[count].Add(p);
    }
    else
    {
        count++;
        resultLists.Add(new List<int>());
    }
    return true;
}).ToList();
like image 535
M.S. Avatar asked May 06 '16 10:05

M.S.


People also ask

How do you split a list into an individual element in Python?

To split a list into n parts in Python, use the numpy. array_split() function. The np. split() function splits the array into multiple sub-arrays.


1 Answers

I'd just go for something simple:

public static IEnumerable<List<int>> SplitWhenNotIncreasing(List<int> numbers)
{
    for (int i = 1, start = 0; i <= numbers.Count; ++i)
    {
        if (i != numbers.Count && numbers[i] > numbers[i - 1])
            continue;

        yield return numbers.GetRange(start, i - start);
        start = i;
    }
}

Which you'd use like so:

List<int> data = new List<int> { 1, 2, 1, 2, 3, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 6 };

foreach (var subset in SplitWhenNotIncreasing(data))
    Console.WriteLine(string.Join(", ", subset));

If you really did need to work with IEnumerable<T>, then the simplest way I can think of is like this:

public sealed class IncreasingSubsetFinder<T> where T: IComparable<T>
{
    public static IEnumerable<IEnumerable<T>> Find(IEnumerable<T> numbers)
    {
        return new IncreasingSubsetFinder<T>().find(numbers.GetEnumerator());
    }

    IEnumerable<IEnumerable<T>> find(IEnumerator<T> iter)
    {
        if (!iter.MoveNext())
            yield break;

        while (!done)
            yield return increasingSubset(iter);
    }

    IEnumerable<T> increasingSubset(IEnumerator<T> iter)
    {
        while (!done)
        {
            T prev = iter.Current; 
            yield return prev;

            if ((done = !iter.MoveNext()) || iter.Current.CompareTo(prev) <= 0)
                yield break;
        }
    }

    bool done;
}

Which you would call like this:

List<int> data = new List<int> { 1, 2, 1, 2, 3, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 6 };

foreach (var subset in IncreasingSubsetFinder<int>.Find(data))
    Console.WriteLine(string.Join(", ", subset));
like image 141
Matthew Watson Avatar answered Sep 16 '22 22:09

Matthew Watson