Python:基于负整数的拆分列表

时间:2017-01-26 00:56:28

标签: python

我有一个名单l = [1,5,8,-3,6,8,-3,2,-4,6,8]。我试图将其拆分为正整数的子列表,即上面的列表会给我[[1,5,8],[6,8],[2],[6,8]]。我尝试了以下内容:

l = [1,5,8,-3,6,8,-3,2,-4,6,8]
index = 0
def sublist(somelist):
    a = []
    for i in somelist:
        if i > 0:
            a.append(i)
        else:
            global index
            index += somelist.index(i)
            break
    return a

print sublist(l)

有了这个,我可以得到第一个子列表([1,5,8])和3的第一个负整数的索引号。现在,如果我再次运行我的函数并将其传递给l[index+1:],我就无法获得下一个子列表,并假设index将更新为显示6。但是,我不能,因为我的生活无法弄清楚如何在循环中运行该函数或使用什么条件,以便我可以继续运行我的函数并给它l[index+1:]其中index是更新的,最近遇到的负整数的位置。任何帮助将不胜感激

4 个答案:

答案 0 :(得分:4)

您需要在此处跟踪两个级别的列表 - 包含子列表的大型列表以及子列表本身。启动一个大型列表,启动子列表,并继续追加到当前子列表,而i是非负的(顺便说一下,包括正数和0)。当i为负时,将当前子列表附加到大列表并启动新的子列表。另请注意,您应该处理第一个元素为负数或最后一个元素不为负数的情况。

l = [1,5,8,-3,6,8,-3,2,-4,6,8]

def sublist(somelist):
    result = []
    a = []
    for i in somelist:
        if i > 0:
            a.append(i)
        else:
            if a: # make sure a has something in it
                result.append(a)
            a = []
    if a: # if a is still accumulating elements
        result.append(a)
    return result

结果:

>>> sublist(l)
[[1, 5, 8], [6, 8], [2], [6, 8]]

答案 1 :(得分:3)

由于somelist永远不会更改,因此重新运行index将始终获取元素的第一个实例的索引,而不是刚刚达到的元素的索引。我建议在循环时查看enumerate来获取索引和元素,因此不需要调用索引。

那就是说,你可以使用附带的电池来解决这个问题,使用itertools.groupby

from itertools import groupby

def sublist(somelist):
    return [list(g) for k, g in groupby(somelist, key=(0).__le__) if k]

仍然值得通过你的代码来理解它,但上面的内容会变得非常简单。

答案 2 :(得分:1)

此代码使用此URL中的概念: Python list comprehension- "pop" result from original list?

在此处针对您的问题应用一个有趣的概念,以下是目前为止其他人为此问题发布的内容的一些替代方案。两者都使用列表推导并被评论来解释第二个选项与第一个选项的目的。这个实验对我来说是我学习曲线的一部分,但也希望它可以帮助你和其他人在这个线程上:

如果您的输入列表非常大,那么您不必将内存开支增加一倍以完成工作。当你缩小另一个时,你建立了一个。

此代码在Python 2.7和Python 3.6上进行了测试:

o1 =  [1,5,8,-3,6,9,-4,2,-5,6,7,-7, 999, -43, -1, 888]    
                                # modified version of poster's list
o1b = [1,5,8,-3,6,8,-3,2,-4,6,8]    # poster's list

o2 = [x for x in (o1.pop() for i in range(len(o1))) \
if (lambda x: True if x < 0 else o1.insert(0, x))(x)]

o2b = [x for x in (o1b.pop() for i in range(len(o1b))) \
if (lambda x: True if x < 0 else o1b.insert(0, x))(x)]

print(o1)
print(o2)
print("")

print(o1b)
print(o2b)

它生成这样的结果集(在iPython Jupyter笔记本上):

[1,5,8,6,9,2,6,7,999,888]
[-1,-43,-7,-5,-4,-3]

[1,5,8,6,8,2,6,8]
[-4,-3,-3]

这是另一个版本,它也使用列表推导作为工作马,但以更易读(我认为)的方式功能化代码,并且更容易使用不同的数字列表进行测试。有些人可能更喜欢原始代码,因为它更短:

p1 =  [1,5,8,-3,6,9,-4,2,-5,6,7,-7, 999, -43, -1, 888]    
                                # modified version of poster's list
p1b = [1,5,8,-3,6,8,-3,2,-4,6,8]    # poster's list

def lst_mut_byNeg_mod(x, pLst):     # list mutation by neg nums module
    # this function only make sense in context of usage in 
    # split_pos_negs_in_list()

    if x < 0: return True
    else: 
        pLst.insert(0,x)
        return False

def split_pos_negs_in_list(pLst):
    pLngth = len(pLst)              # reduces nesting of ((()))
    return [x for x in (pLst.pop() for i in range(pLngth)) \
            if lst_mut_byNeg_mod(x, pLst)]

p2 = split_pos_negs_in_list(p1)
print(p1)
print(p2)
print("")
p2b = split_pos_negs_in_list(p1b)
print(p1b)
print(p2b)

最后的想法: 之前提供的链接在评论主题中有许多想法:

  • 建议Google搜索&#34; python bloom过滤器库&#34; - 从表现的角度来看,这听起来很有希望,但我还没有考虑过它
  • 该帖子上有一个帖子,其中有554个投票,但它至少有4条评论说明可能有问题。在探索选项时,最好扫描评论线索,而不仅仅是查看获得最多选票的内容。对于这样的情况,有很多选择。

答案 3 :(得分:0)

只是为了好玩,您也可以使用re进行一次划线。

l = [1,5,8,-3,6,8,-3,2,-4,6,8]
print map(lambda x: map(int,x.split(",")), re.findall(r"(?<=[,\[])\s*\d+(?:,\s*\d+)*(?=,\s*-\d+|\])", str(l)))

输出:[[1, 5, 8], [6, 8], [2], [6, 8]]