在python中,如何按特定项目剪切列表?

时间:2018-12-25 13:28:39

标签: python list

我正在尝试按列表中的特定项目剪切列表,例如,我有一个这样的列表:

down = ["a", "b", "c", "d", "b", "e", "r"]

我想要的是

[["a", "b"]["c", "d", "b"] ["e", "r"]]

在每次发生"b"之后被削减。

我写了这样的东西:

down = ["a", "b", "c", "d", "b", "e", "r"]
up = []
while down is not []:
    up, down = up.append(down[:(down.index("b") + 1)]), down[(down.index("b") + 1):]

它抛出一个错误:

AttributeError: 'NoneType' object has no attribute 'append'

我不知道怎么了。

9 个答案:

答案 0 :(得分:3)

您可以迭代原始列表并将子列表组合在第二个列表中:

k = ["a", "b", "c", "d", "b", "e", "r"]

result = [[]]
for e in k:
    if e != "b":
        result[-1].append(e)
    else:
        result[-1].append(e)
        result.append([])

if result[-1] == []: 
    result.pop() # thx iBug's comment

print(result) # [['a', 'b'], ['c', 'd', 'b'], ['e', 'r']]

我认为这比您的代码尝试做的要清楚得多-您的“我想要的["a", "b"]["c", "d", "b"] ["e", "r"]”不是有效的python。


性能稍差的代码是:

k = ["a", "b", "c", "d", "b", "e", "r"]
b = []
while True:
    try:
        b_idx = k.index("b")
    except: 
        b.append(k)
        break
    else:
        b,k = b+[k[:b_idx+1]],k[b_idx+1:]
print(b) 

但是您需要通过.index()try: except对列表进行更深入的搜索,因此其性能较差,然后仅对列表进行一次迭代即可。

答案 1 :(得分:1)

list.append(elem)不返回新列表,仅修改原始列表。这就是导致您出错的原因。

在不更改方法的情况下更正代码:

down = ["a", "b", "c", "d", "b", "e", "r"]
up = []
while True:
    if 'b' in down: # make sure there is a 'b' in the list
        index = down.index("b") # get the index of the first "b"
        up.append(down[:index + 1]) # save first sublist in up
        down = down [index + 1:] # trim the sublist you already saved 
    else:
        up.append(down) # add the rest of down
        break # leave the loop 
print(up)

答案 2 :(得分:1)

如果没有itertools答案,这样的问题会是什么?

在这种情况下,您可以将groupby与自定义键一起使用,该自定义键可以统计过去'b'的出现次数:

from itertools import groupby

class CountKey:
    def __init__(self, what):
        self.what = what
        self.count = 0
    def __call__(self, item):
        count = self.count
        if item == self.what:
            self.count += 1
        return count

up = [list(g) for k, g in groupby(down, CountKey('b'))]

答案 3 :(得分:1)

您可以构造一个索引列表,然后使用列表理解:

down = ["a", "b", "c", "d", "b", "e", "r"]

n = len(down)
idx = [index+1 for index, value in enumerate(down) if value == 'b']

res = [down[i: j] for i, j in zip([0] + idx, idx + ([n] if idx[-1] != n else []))]

# [['a', 'b'], ['c', 'd', 'b'], ['e', 'r']]

如果[n] if idx[-1] != n else []中的最后一个值为down,则使用三元语句'b'来避免空的最终列表。这是一种两遍解决方案,但是使用列表切片,而不是一次显式地追加一项。

答案 4 :(得分:1)

这是一个简单的单线来完成这项工作:

import re

d = ["a", "b", "c", "d", "b", "e", "r"]

s = '(?<=b)'

print ([list(x) for x in re.split(s,"".join(d))])

输出:

[['a', 'b'], ['c', 'd', 'b'], ['e', 'r']]

这里的难点在于将分隔符保留在“左”子列表中。 re.split() 方法可以与积极的前瞻相关联地做到这一点。

答案 5 :(得分:0)

down = ["a", "b", "c", "d", "b", "e", "r"]
poslist = []
for pos, item in enumerate(down):
    if item == 'b':
        poslist.append(pos)
answerlist = []
for i in range(len(poslist)):
    if i == 0:
        answerlist.append(down[:poslist[i]+1])
    else:
        answerlist.append(down[poslist[i-1]+1:poslist[i]+1])
answerlist.append(down[poslist[i]+1:])
print (answerlist)
# [['a', 'b'], ['c', 'd', 'b'], ['e', 'r']]

答案 6 :(得分:0)

down = ["a", "b", "c", "d", "b", "e", "r"]
indices = [i for i, x in enumerate(down ) if x == "b"]
curr=0
master_list=[]
for item in indices:
    master_list.append(down[curr:item+1])
    print(master_list)
    curr=item+1
if curr !=len(down):
    master_list.append(down[curr:len(down)])
print(master_list)

答案 7 :(得分:0)

In [59]: k
Out[59]: ['a', 'b', 'c', 'd', 'b', 'e', 'r', 'l', 'f', 'b', 's']

In [60]: indices = [i for i, x in enumerate(k) if x == "b"]  # all index of 'b'

In [61]: aa = k[:indices[0]+1] # first list

In [62]: bb = k[indices[len(indices)-1]+1:]  # last list

In [63]: for i in range(0, len(indices)-1):
    ...:     print(k[indices[i]+1:indices[i+1]+1]) # remaining list
    ...: 
['c', 'd', 'b']
['e', 'r', 'l', 'f', 'b']

In [64]: aa
Out[64]: ['a', 'b']

In [65]: bb
Out[65]: ['s']

答案 8 :(得分:0)

import re

l = ['a', 'b', 'c', 'd', 'b', 'e', 'r']
split_by = 'b'

pattern = re.compile(r'(.*?{0})'.format(split_by))
split_list = re.split(pattern, ('').join(l))
result = [list(i) for i in split_list if i]

print(result) # [['a', 'b'], ['c', 'd', 'b'], ['e', 'r']]