In the Python If there are
[1,2,3,4,1,2,3,1,2,1]
lists, I want to split the list when the size is reduced like this
[1,2,3,4], [1,2,3], [1,2], [1]
How do I code it?
In the Python If there are
[1,2,3,4,1,2,3,1,2,1]
lists, I want to split the list when the size is reduced like this
[1,2,3,4], [1,2,3], [1,2], [1]
How do I code it?
You can use Pandas to do this in three lines:
import pandas as pd
s = pd.Series([1,2,3,4,1,2,3,1,2,1])
s.groupby(s.diff().lt(0).cumsum()).apply(list).tolist()
Output:
[[1, 2, 3, 4], [1, 2, 3], [1, 2], [1]]
First create a pandas series from the list, then use the diff method in pd.Series to get the difference from the previous value:
s.diff()
0 NaN
1 1.0
2 1.0
3 1.0
4 -3.0
5 1.0
6 1.0
7 -2.0
8 1.0
9 -1.0
dtype: float64
The negative values are indicate the start of a new "sub" list. So, we use lt(0) to mark those records where a new "sub" list should start.
s.diff().lt(0)
0 False
1 False
2 False
3 False
4 True
5 False
6 False
7 True
8 False
9 True
dtype: bool
Next, we are going to use cumsum to create a grouping term. cumsum will only increment when True, so all falses that are next to each other get the same value, then True increments and next group of falses get that new value, until the next True.
s.diff().lt(0).cumsum()
0 0
1 0
2 0
3 0
4 1
5 1
6 1
7 2
8 2
9 3
dtype: int32
Now, we can use groupby with apply to create a new series with these sublist as rows. We are grouping on that newly create grouping term from above and apply the python list to those values in a that group, thus creating the "sub" list.
s.groupby(s.diff().lt(0).cumsum()).apply(list)
0 [1, 2, 3, 4]
1 [1, 2, 3]
2 [1, 2]
3 [1]
dtype: object
Lastly, we apply the tolist method on the series to return the series as a list.
s.groupby(s.diff().lt(0).cumsum()).apply(list).tolist()
Final Output:
[[1, 2, 3, 4], [1, 2, 3], [1, 2], [1]]
This might be the algorithm you are looking for -
a=[1,2,3,4,1,2,3,1,2,1]
b=[]
c=[]
for i in range(len(a)-1):
b.append(a[i])
if a[i] > a[i+1]:
c.append(b)
b=[]
print(c)
It outputs a list of sorted lists -
[[1, 2, 3, 4], [1, 2, 3], [1, 2]]
Let me know if that helps.
If you are looking to split the list when the next number is less than previous one than this might help:
arr = [1,2,3,4,1,2,3,1,2,1]
b = []
start = 0
for i in range(len(arr)):
if(arr[i] < arr[i-1]):
b.append(arr[start:i])
start = i
b.append(arr[start:])
print(b)
Output:
[[1, 2, 3, 4], [1, 2, 3], [1, 2], [1]]
Hope this helps.
Just for fun, I wanted to see if you could rework the code given in the docs as a sample implementation of itertools.groupby to suit your needs in a general way. The result is a generator whose elements are sub-generators representing your sub-lists. The determination when to split is done by a user-defined function of two variables that accepts each successive pair of neighboring elements and returns True when they are in different groups:
from collections import deque
class splitby:
# [''.join(s) for s in splitby('AAAABBBCCDAABBB', operator.eq)] --> ['AAAA', 'BBB', 'CC', 'D', 'AA', 'BBB']
def __init__(self, iterable, splitter):
self.splitfunc = splitter
self.it = iter(iterable)
self.segment = None
def __iter__(self):
return self
def __next__(self):
if self.segment:
deque(self.segment, maxlen=0)
if self.segment is None:
raise StopIteration
else:
self.curvalue = next(self.it)
self.segment = self._splitter()
return self.segment
def _splitter(self):
split = False
while not split:
yield self.curvalue
prev = self.curvalue
try:
self.curvalue = next(self.it)
except StopIteration:
self.segment = None
return
split = self.splitfunc(prev, self.curvalue)
The whole thing can be applied to your input list with a splitter function of operator.gt or int.__gt__ if your list will only ever contain ints. A suitable wrapping in list will not only properly consume the elements, but will also make the output match your question:
from operator import gt x = [1, 2, 3, 4, 1, 2, 3, 1, 2, 1] [list(s) for s in splitby(x, gt)]
The result is:
[[1, 2, 3, 4], [1, 2, 3], [1, 2], [1]]
Here is an IDEOne link: https://ideone.com/UW483U
TL;DR
This is massive overkill for most situations, so don't do it this way. I was just having some fun, but the code here does technically solve your problem. If you put the class into your library somewhere, the actual usage is a one-liner.