我是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
感谢您提出建议或其他想法!
P.S。
一些输入将是:
输入:[45,78,120,47,58,50,32,34]
输出:[45,78,120],[47,58],50,[32,34]
为什么我想要制作一个双循环,因为要比较完整列表的子组,换句话说是45是小于下一个只是添加在新列表中,如果没有采取下一个比较in这个案子将是47并开始与58进行比较。
答案 0 :(得分:5)
没有循环! 至少,没有显式循环......
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)))
答案 1 :(得分: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]]
前缀函数基本上将列表拆分为2;第一部分由第一个升序数字组成,第二部分是仍然需要处理的其余部分(如果我们完成,则为空列表)。
然后,main函数简单地组装结果列表中的第一部分,然后将其余部分交给内部函数。
我不确定单值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]]
答案 2 :(得分: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()
中使用sublist
。这不是那么明显,虽然。)
答案 3 :(得分:-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]]