Find monotonic sequences in a list?

后端 未结 4 404
一整个雨季
一整个雨季 2020-12-11 23:52

I\'m new in Python but basically I want to create sub-groups of element from the list with a double loop, therefore I gonna compare the first element with the next to figure

4条回答
  •  爱一瞬间的悲伤
    2020-12-12 00:20

    No loop! Well at least, no explicit looping...

    import itertools
    
    def process(lst):
        # Guard clause against empty lists
        if len(lst) < 1:
            return lst
    
        # use a dictionary here to work around closure limitations
        state = { 'prev': lst[0], 'n': 0 }
    
        def grouper(x):
            if x < state['prev']:
                state['n'] += 1
    
            state['prev'] = x
            return state['n']
    
        return [ list(g) for k, g in itertools.groupby(lst, grouper) ]
    

    Usage (work both with Python 2 & Python 3):

    >>> data = [45,78,120,47,58,50,32,34]
    >>> print (list(process(data)))
    [[45, 78, 120], [47, 58], [50], [32, 34]]
    

    Joke apart, if you need to group items in a list itertools.groupby deserves a little bit of attention. Not always the easiest/best answer -- but worth to make a try...


    EDIT: If you don't like closures -- and prefer using an object to hold the state, here is an alternative:

    class process:
        def __call__(self, lst):
            if len(lst) < 1:
                return lst
    
            self.prev = lst[0]
            self.n = 0
    
            return [ list(g) for k, g in itertools.groupby(lst, self._grouper) ]
    
        def _grouper(self, x):
            if x < self.prev:
                self.n += 1
    
            self.prev = x
            return self.n
    
    
    
    data = [45,78,120,47,58,50,32,34]
    print (list(process()(data)))
    

    EDIT2: Since I prefer closures ... but @torek don't like the dictionary syntax, here a third variation around the same solution:

    import itertools
    
    def process(lst):
        # Guard clause against empty lists
        if len(lst) < 1:
            return lst
    
        # use an object here to work around closure limitations
        state = type('State', (object,), dict(prev=lst[0], n=0))
    
        def grouper(x):
            if x < state.prev:
                state.n += 1
    
            state.prev = x
            return state.n
    
        return [ list(g) for k, g in itertools.groupby(lst, grouper) ]
    
    data = [45,78,120,47,58,50,32,34]
    print (list(process(data)))
    

提交回复
热议问题