Создание цикла внутри оператора цикла for в Python

#python #loops #for-loop #insert

#python #циклы #for-цикл #вставить

Вопрос:

У меня есть начальное list имя vbn . Я имею в виду функцию, которая добавляет 0 после каждого 0 в списке.

Так что vbn = [1,0,2,3,0,4,5,0] это превращается в vbn = [1,0,0,2,3,0,0,4,5,0,0] .

Я использовал for цикл и .insert() метод для этого и получил результат ниже.

 vbn = [1,0,2,3,0,4,5,0]
s = 0
for i,j in enumerate(vbn[s:]):
    if j == 0:
        vbn.insert(i 1,0)
        s  = i 2
print(vbn)
 

Выводит:

 [1, 0, 0, 2, 3, 0, 0, 4, 0, 5, 0]
 

Из того, что я понял в своем коде, на s оператор in my for loop итерация вообще не влияет. s однако внутри цикла изменения происходят так, как ожидалось.

Может кто-нибудь, пожалуйста, объяснить, почему это так? И как я могу решить проблему.

Заранее спасибо!

Ответ №1:

Ваша проблема в том, что индексы, в которые вы вставляете, больше не действительны после первой вставки, потому что вы увеличили размер списка. Если вы измените свой код на insert x вместо 0 , и print vbn на каждой итерации цикла, вы сможете увидеть, что происходит:

 vbn = [1,0,2,3,0,4,5,0]
s = 0
for i,j in enumerate(vbn[s:]):
    if j == 0:
        vbn.insert(i 1,'x')
        s  = i 2
    print(vbn)
 

Вывод:

 [1, 0, 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 'x', 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 'x', 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 'x', 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 'x', 0, 4, 'x', 5, 0]
 

Как вы можете видеть, даже вторая вставка происходит не в том месте. Вы можете обойти это, добавив смещение к точке вставки и увеличивая это смещение каждый раз, когда вы делаете вставку:

 vbn = [1,0,2,3,0,4,5,0]
s = 0
o = 1
for i,j in enumerate(vbn[s:]):
    if j == 0:
        vbn.insert(i o,'x')
        s  = i 2
        o  = 1
    print(vbn)
 

Вывод (в этом случае вы можете видеть x , что он вставляется в те места, которые вы ожидаете):

 [1, 0, 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 'x', 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 'x', 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 'x', 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 'x', 4, 5, 0, 'x']
 

Просто измените значение x back на a 0 , чтобы получить желаемый результат. Обратите внимание, что я не уверен, для чего s = i 2 предназначен код; Я оставил его в предположении, что вы используете его после цикла.

Комментарии:

1. Я полагаю s = 2 , что это была попытка OP изменить индекс, вызываемый в цикле, я как раз собирался прокомментировать, что он ничего не делает в самом цикле.

2. Пожалуйста, обратите внимание, что python оценивает оператор цикла for только один раз в начале цикла, s поэтому изменения в нем не учитываются в инструкции внутри условий цикла for.

3. @LeoE абсолютно, иначе код вообще не работал бы. ОП, похоже, тоже понимает, что это так.

Ответ №2:

В качестве альтернативного метода, если вы не хотите повторять несколько значений, это создать новый массив в цикле:

 vbn = [1,0,2,3,0,4,5,0]
new = []

for i in vbn:
    if i == 0:
        new  = [i, 0]
    else:
        new  = [i]
print(new)
 

Комментарии:

1. Это приятно и просто. Вы могли бы даже сделать это в одной строке: new = [t for x in [[v] if v != 0 else [v, 0] for v in vbn] for t in x]

2. Можете ли вы это объяснить? Я не мог понять, как заставить его работать самостоятельно, и это не очень интуитивное понимание списка, глядя на него.

3. Если вы просто берете внутренний цикл ( [[v] if v != 0 else [v, 0] for v in vbn] ) , он создает список либо записи, либо записи, за которой следует 0 if запись 0 (очень похожа на ваш цикл), т.е. [[1], [0, 0], [2], [3], [0, 0], [4], [5], [0, 0]] . Затем два внешних цикла сглаживают этот список.

4. это [t for x in * for t in x] просто python? Я могу разбить внутренний [[v] if v != 0 else [v, 0] for v in vbn] цикл на стандартный цикл for , но внешняя секция — это то, что меня бросает.

5. Да, если вы выполните поиск по python flatten list, это то, что вы найдете (с > 5000 голосов!)

Ответ №3:

Вы можете попытаться создать новый список и вставить элемент (ненулевое число или два нуля) в vbn в новый список.

 vbn = [1,0,2,3,0,4,5,0]
newlist = []
for i in vbn: 
    if i == 0: 
        newlist.insert(len(newlist),i)
        newlist.insert(len(newlist),0)
    else: 
        newlist.insert(len(newlist),i)   
print (newlist)
 

Отображаемые результаты:

 [1, 0, 0, 2, 3, 0, 0, 4, 5, 0, 0]
 

Ответ №4:

Хотя я не мог понять причину, по которой s в цикле не повторяется; я, однако, заметил другую проблему в коде, т.Е. Каждый раз, когда вы устанавливаете значение s как s (i 2), например, 0 (1 2), в другой раз его значение изменяется как 3 (i 2) вместо 0 (i 2)

Хотя у меня есть альтернативное решение для вашего вопроса, т.е.

 vbn = [1,0,2,3,0,4,5,0]
s = 0
arr = []*10 #list to store no. of positions we need to add 0 
for i,j in enumerate(vbn):
  if j == 0:
    arr.append(i)
m=0 #variable to keep count of number of times the list is extended before the current one
for k in arr:
  k =m #since, when we add zero to the list the current positions of elements changes
  vbn.insert(k 1,0)
  m =1
print(vbn)