3

我是 Python 新手,但基本上我想用双循环从列表中创建元素的子组,因此我会将第一个元素与下一个元素进行比较,以确定是否可以创建这些子列表,否则我会破坏在里面循环,我想继续最后一个元素,但在主循环中:

例子:5,7,8,4,11

比较 5 和 7,是次要的吗?是的,所以包括在新列表中,并在里面继续下一个 8,小于 5?是的,所以包括在新列表中,但是当与 4 比较时,我打破了循环,所以我想继续在 m 中使用这 4 个从下一个开始,在本例中为 11...

for m in xrange(len(path)):
    for i in xrange(m+1,len(path)):
              if (path[i] > path[m]):
                  newlist.append(path[i])

             else:
                  break

             m=m+i

感谢您提出建议或其他想法来实现它!

PS一些输入将是:输入:[45,78,120,47,58,50,32,34] 输出:[45,78,120],[47,58],50,[32,34]

由于比较完整列表的子组,我为什么要进行双循环的想法是,而 45 比下一个小,只需添加到新列表中,如果在这种情况下不采用下一个比较将47岁开始和58岁比较。

4

4 回答 4

6

没有循环!至少,没有显式循环......

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) ]

用法(使用 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]]

开个玩笑,如果您需要对列表中的项目进行分组itertools.groupby,则值得关注。并不总是最简单/最好的答案——但值得一试......


编辑:如果你不喜欢闭包——并且更喜欢使用一个对象来保存状态,这里有一个替代方案:

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:因为我更喜欢闭包......但@torek 不喜欢字典语法,这里是围绕相同解决方案的第三个变体:

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)))
于 2013-06-08T17:36:58.643 回答
0

我也使用了双循环,但将内部循环放在一个函数中:

#!/usr/bin/env python

def process(lst):

    def prefix(lst):
        pre = []
        while lst and (not pre or pre[-1] <= lst[0]):
            pre.append(lst[0])
            lst = lst[1:]
        return pre, lst

    res=[]
    while lst:
        subres, lst = prefix(lst)
        res.append(subres) 
    return res

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

prefix 函数基本上将一个列表分成 2 个;第一部分由第一个升序数字组成,第二部分是仍然需要处理的其余部分(或空列表,如果我们完成了)。

然后主函数简单地将第一部分组装到结果列表中,并将其余部分交还给内部函数。

我不确定单个值 50;在您的示例中,它不在子列表中,但在我的示例中。如果是要求,则更改

        res.append(subres) 

        res.append(subres[0] if len(subres)==1 else subres)

print process([45,78,120,47,58,50,32,34])
=> [[45, 78, 120], [47, 58], 50, [32, 34]]
于 2013-06-08T16:18:28.900 回答
0

@uselpa 的版本很好。这是我的(与 [50] 相同的问题,而不仅仅是 50),它collections.deque曾经效率更高,还有一些长评论......

#! /usr/bin/env python

from collections import deque

def process(lst):
    """
    Given a list of values that is not sorted (such that for some
    valid indices i,j, i<j, sometimes lst[i] > lst[j]), produce a
    new list-of-lists, such that in the new list, each sublist *is*
    sorted:
        for all sublist \elem returnval:
            assert_is_sorted(sublist)
    and furthermore this is the minimal set of sublists required
    to achieve the condition.

    Thus, if the input list lst is actually sorted, this returns
    [list(lst)].
    """
    def sublist(deq):
        """
        Pop items off the front of deque deq until the next one
        goes backwards.  Return the constructed sub-list.
        """
        sub = [deq.popleft()]
        while deq and deq[0] >= sub[-1]:
            sub.append(deq.popleft())
        return sub

    # Make a copy of lst before modifying it; use a deque so that
    # we can pull entries off it cheaply.
    deq = deque(lst)
    output = []
    ret = []
    while deq:
        ret.append(sublist(deq))
    return ret

print process([45,78,120,47,58,50,32,34])

(顺便说一句,在以前的日子里,collections.deque我可能只是使用lst和使用lst.pop()in的反向副本sublist。不过,这并不那么明显。)

于 2013-06-08T16:46:42.773 回答
-1

为什么不简单地使用单个 for 循环而不是使用 itertool 和所有花哨的东西。

def list_test(inlist, outlist):
    if not inlist:
        return []
    prev=inlist[0]
    x=[]
    for item in inlist:
        if item >= prev:
            x.append(item)
        else:
            outlist.append(x)
            x=[]
            x.append(item)
        prev=item
    if x:
        outlist.append(x)


in_list=[1,0,1,2,3]
out_list = []
list_test(in_list, out_list)    
print(out_list)

O/p:[[1], [0, 1, 2, 3]]

于 2020-06-26T12:17:58.197 回答