Я пытаюсь разрезать список по определенным элементам в нем, например, у меня есть такой список:
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'
Я не могу понять, что случилось.
Спасибо ! Вот в чем я запутался. Я переписал свой код так: down = ["a", "b", "c", "d", "b", "e", "r"] up = [] while "b" in down: up.append(down[:(down.index("b") + 1)]) down = down[(down.index("b") + 1):] up.append(down) @ParitoshSingh
@ frankzheng43 ознакомьтесь с моим ответом, он вам может показаться интересным!






Вы получаете сообщение об ошибке, потому что вы назначаете результат функции list.append(), то есть None, на up в
up, down = up.append(down[: (down.index("b") + 1)]), down[...snipp...] # ^^^^^^^^ returns None
list.append - это операция «на месте», которая возвращает None, поэтому в следующей итерации up будет None.
Держитесь ближе к тому, что у вас есть, вы могли бы использовать
down = ["a", "b", "c", "d", "b", "e", "r"]
up = []
while 'b' in down:
b_index = down.index('b') + 1
up.append(down[:b_index])
down = down[b_index:]
up.append(down)
но, на мой взгляд, простая итерация вашего оригинала и сборка подсписок во втором списке более чистая:
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"]» не является допустимым питоном.
Немного другая версия кода:
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, поэтому у него будет худшая производительность, чем при простом повторении списка один раз.
result = result[:-1] -> result.pop()Какие достоинства дв на 2й старый вопрос? Предложение что улучшить?
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']]
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)
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']
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)
Каким был бы такой вопрос без ответа 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'))]
Вы можете составить список индексов, а затем использовать его понимание:
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'. Это двухпроходное решение, но в нем используется нарезка списка, а не явное добавление элементов по одному.
Вот простой однострочник, чтобы выполнить эту работу:
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() может сделать это в сочетании с положительным прогнозом.
У @patrick есть ответ, который вам нужен. насчет того, что не так, вы пытаетесь назначить
upсup.append(something). вы не должны назначать при использовании метода / функции списка. В итоге происходит то, что метод append изменяет объект, а затем функция возвращает None. В сочетании с назначением вы изменяете список, но затем связываете имяupсо значением «Нет». На следующей итерации вы получите отображаемую ошибку.