Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slicing a list into sublists based on condition [duplicate]

I want to slice this list of numbers:

num_list = [97, 122, 99, 98, 111, 112, 113, 100, 102] 

into multiple sublists. The condition for slicing is that the numbers in each sublist should be in increasing order.

So the final result will look like this:

 list_1 = [97, 122]
 list_2 = [99]
 list_3 = [98, 111, 112, 113]
 list_4 = [100, 102]

Can anyone help me to solve this problem please? Thanks a lot

like image 622
Huy Nguyen Bui Avatar asked Sep 28 '18 08:09

Huy Nguyen Bui


People also ask

Does slicing a list create a copy?

Slicing lists does not generate copies of the objects in the list; it just copies the references to them. That is the answer to the question as asked.

How do you split a list into two sublists in Python?

Split List Into Sublists Using the array_split() Function in NumPy. The array_split() method in the NumPy library can also split a large array into multiple small arrays. This function takes the original array and the number of chunks we need to split the array into and returns the split chunks.


2 Answers

I've quickly written one way to do this, I'm sure there are more efficient ways, but this works at least:

num_list =[97, 122, 99, 98, 111, 112, 113, 100, 102]

arrays = [[num_list[0]]] # array of sub-arrays (starts with first value)
for i in range(1, len(num_list)): # go through each element after the first
    if num_list[i - 1] < num_list[i]: # If it's larger than the previous
        arrays[len(arrays) - 1].append(num_list[i]) # Add it to the last sub-array
    else: # otherwise
        arrays.append([num_list[i]]) # Make a new sub-array 
print(arrays)

Hopefully this helps you a bit :)

like image 196
DeltaMarine101 Avatar answered Oct 08 '22 19:10

DeltaMarine101


Here is a one-linear Numpythonic approach:

np.split(arr, np.where(np.diff(arr) < 0)[0] + 1)

Or a similar approach to numpy code but less efficient:

from operator import sub
from itertools import starmap
indices = [0] + [
                  i+1 for i, j in enumerate(list(
                        starmap(sub, zip(num_list[1:], num_list)))
                    ) if j < 0] + [len(num_list)
                ] + [len(num_list)]

result = [num_list[i:j] for i, j in zip(indices, indices[1:])]

Demo:

# Numpy
In [8]: np.split(num_list, np.where(np.diff(num_list) < 0)[0] + 1)
Out[8]: 
[array([ 97, 122]),
 array([99]),
 array([ 98, 111, 112, 113]),
 array([100, 102])]

# Python
In [42]: from operator import sub

In [43]: from itertools import starmap

In [44]: indices = [0] + [i+1 for i, j in enumerate(list(starmap(sub, zip(num_list[1:], num_list)))) if j < 0] + [len(num_list)]

In [45]: [num_list[i:j] for i, j in zip(indices, indices[1:])]
Out[45]: [[97, 122], [99], [98, 111, 112, 113], [100, 102]]

Explanation:

Using np.diff() you can get the differences of each item with their next item (up until the last element). Then you can use the vectorized nature of numpy to get the indices of the places where this difference is negative, which can be done with a simple comparison and np.where(). Finally you can simply pass the indices to np.split() to split the array based on those indices.

like image 36
Mazdak Avatar answered Oct 08 '22 17:10

Mazdak