Форум сайта python.su
всем привет
интересно вот что - можно ли удалять или модифицировать массив или словарь внутри цикла по самому этому массиву?
вот такой вариант - у меня ломал данные, когда arr был листом.
for idx, v in arr:
if something():
del(arr[idx]);
for k, v in slovar.iteritems():
if something():
del(slovar[k]);
Офлайн
Что такое “массив”?
В питоне есть только один массив - это ассоциативный массив aka “словарь”. Или это просто как синоним коллекции?
Ответ - нельзя.
iteritems - возвращает итератор с словаря, что не есть словарь, т.е. словарь может модифицироватся, на работу итератора в цикле, на прямую, не повлияет.
Для списка можно использовать такой приём (он есть, кстати, в официальном туториале):
for idx, v in arr[:]:
а вот будет ли корректно работать словарь?Не стоит на это полагаться.
Отредактировано (Авг. 18, 2009 16:41:29)
Офлайн
Чем не вариант для словаря?
>>> d = {1: 'a', 2: 'b', 3: 'c', 0: 'z'}
>>> for k, v in list(d.iteritems()):
... if v < 'c':
... del d[k]
...
>>> d
{0: 'z', 3: 'c'}
>>> l = ['a', 'b', 'c']
>>> for i, v in list(enumerate(l))[::-1]:
... if v < 'c':
... del [i]
...
>>> l
['c']
Отредактировано (Авг. 18, 2009 17:52:55)
Офлайн
так как выполняется его копия (и приводится к списку).Это не правда. iteritems не приводит словарь к списку.
Отредактировано (Авг. 18, 2009 18:18:31)
Офлайн
както я больше запутался - чем разобрался. пожалуй укажу типы данных в моем примере выше.
arr = [1, 2, 3, 'd', 'c']
for idx, v in enumerate(arr):
if something():
del(arr[idx])
slovar = {'s':'s', 'd':'f'}
for k, v in slovar.iteritems():
if something():
del(slovar[k]);
Отредактировано (Авг. 18, 2009 18:49:05)
Офлайн
> Это не правда. iteritems не приводит словарь к списку.
Будь внимательнее – list(d.iteritems()). Ну я тут конечно загнул, достаточно использовать .items().
Вот я блин даю :-), так можно сделать:
>>> d = {1: 'a', 2: 'b', 3: 'c', 0: 'z'}
>>> dict(filter(lambda (k, v): 'c' <= v, d.iteritems()))
{0: 'z', 3: 'c'}
>>> l = ['a', 'b', 'c']
>>> filter(lambda v: 'c' <= v, l)
['c']
Отредактировано (Авг. 18, 2009 19:07:32)
Офлайн
Или есть такой вариант:
>>> l = ['a', 'b', 'c']
>>> [v for v in l if 'c' <= v]
['c']
Офлайн
нет это все понятно - но вопрос не в этом. вопрос в том можно ли в ЦИКЛЕ изменять (удалять добавлять новые элементы) СЛОВАРЬ или ЛИСТ по которому ты бегаешь. предложенные варианты, это все ясно - но они не подходят когда цикл должен содержать более сложную логику, на основе которой принимается решение - по удалению или удалению новых элементов в СЛОВАРЬ или ЛИСТ по которому бегаешь.
Офлайн
> можно ли в ЦИКЛЕ изменять (удалять добавлять новые элементы) СЛОВАРЬ или ЛИСТ по которому ты бегаешь
Можно, как показано выше, в примере с созданием копии словаря/списка.
> подходят когда цикл должен содержать более сложную логику
Вынеси логику в функцию и передай эту функцию filter. Не вижу здесь проблем.
>>> def something(value):
... if value < 'c':
... return False
... return True
...
>>> l = ['a', 'b', 'c', 'z']
>>> l = filter(something, l)
>>> l
['c', 'z']
Отредактировано (Авг. 19, 2009 12:16:10)
Офлайн
Если мне в цикле нужно модифицировать список, я пробегаю не по нему , а по его номерам. Если ещё и удалять понадобится, то иду в обратную сторону. Хоть и выглядит не так красиво, зато заморачиваться не приходится
for num in xrange(len(spisok)-1:-1:-1):
if something():
del(spisok[num]);
Офлайн