Почему некоторые языки программирования ограничивают Вас в редактировании массива, Вы - цикличное выполнение через?

Можно использовать time.strftime() :

>>> from time import gmtime, strftime
>>> strftime("%Y-%m-%d %H:%M:%S", gmtime())
'2009-01-05 22:14:39'

6
задан 3 revs, 2 users 95% 20 August 2009 в 22:08
поделиться

9 ответов

Каким должно быть поведение?

list = [1,2,3,4]
foreach x in list:
    print x
    if x == 2: list.remove(1)

возможные варианты поведения:

list - это некоторый итератор типа связанного списка, удаление которого не влияет на ваш текущий итератор:

[1,2,3,4]

list - это некоторый массив, в котором ваш итератор выполняет итерацию с помощью приращения указателя:

[1,2,4] 

так же, как и раньше, только система пытается кэшировать счетчик итераций

[1,2,4,<segfault>]

Проблема в том, что разные коллекции реализуют этот интерфейс перечисления / последовательности, который позволяет выполнять цикл foreach иметь разное поведение.

9
ответ дан 8 December 2019 в 12:21
поделиться

В зависимости от языка (или платформы, например .Net) итерация может быть реализована по-разному.

Обычно foreach создает объект Iterator или Enumerator в массиве, который внутренне сохраняет свое состояние о деталях итерации. Если вы измените массив (добавив или удалив элемент), состояние итератора будет несовместимо с новым состоянием массива.

Такие платформы, как .Net, позволяют вам определять свои собственные счетчики, которые могут быть невосприимчивыми. для добавления / удаления элементов базового массива.

Общее решение проблемы добавления / удаления элементов во время итерации состоит в том, чтобы собрать элементы в новом списке / коллекции / массиве и добавить / удалить собранные элементы после перечисления завершено.

4
ответ дан 8 December 2019 в 12:21
поделиться

Предположим, ваш массив состоит из 10 элементов. Вы переходите к 7-му элементу и решаете, что вам нужно добавить новый элемент раньше в массив. Ой-ой! Этот элемент не повторяется! для каждого имеет семантику, по крайней мере, для меня, работы с каждым без исключения элементом массива один раз и только один раз.

3
ответ дан 8 December 2019 в 12:21
поделиться

Массивы обычно имеют фиксированное количество элементов. Вы получаете гибкую ширину размера за счет обернутых объектов (например, List), которые обеспечивают гибкость. Я подозреваю, что у языка могут быть проблемы, если использованный механизм создал совершенно новый массив для редактирования.

1
ответ дан 8 December 2019 в 12:21
поделиться

Ваш псевдо-пример кода приведет к бесконечному циклу. Для каждого просматриваемого элемента вы добавляете один в коллекцию, следовательно, если у вас есть хотя бы 1 элемент для начала, у вас будет i (итерационный счетчик) + 1 элемент.

1
ответ дан 8 December 2019 в 12:21
поделиться

Многие компилируемые языки реализуют циклы «for» с предположением, что количество итераций будет вычисляться один раз при запуске цикла (или, еще лучше, во время компиляции). Это означает, что если вы измените значение переменной «to» внутри цикла «for i = 1 to x», это не изменит количество итераций. Это позволяет использовать множество оптимизаций циклов, которые очень важны для ускорения работы приложений, обрабатывающих числа.

Если вам не нравится эта семантика, идея состоит в том, что вы должны вместо этого использовать языковую конструкцию «while»

. ] Обратите внимание, что при таком взгляде на мир C и C ++ не имеют собственных циклов «for», а только причудливые циклы «while».

1
ответ дан 8 December 2019 в 12:21
поделиться

Реализация списков и счетчиков для обработки этого потребовала бы больших накладных расходов. Эти накладные расходы будут всегда, и они будут полезны только в огромном меньшинстве случаев.

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

0
ответ дан 8 December 2019 в 12:21
поделиться

Это происходит только внутри блоков foreach. Используйте цикл for со значением индекса, и вам это будет разрешено. Просто не забудьте выполнить итерацию в обратном порядке, чтобы можно было удалять элементы, не вызывая проблем.

0
ответ дан 8 December 2019 в 12:21
поделиться

Насколько я знаю, может быть два сценария реализации итерации коллекции.

  1. итератор выполняет итерацию по коллекции, для которой он был создан

  2. итератор выполняет итерацию по копии коллекции, для которой он был создан

, когда изменения вносятся в коллекцию «на лету», первый вариант должен либо обновить свою итерационную последовательность (что может быть очень сложно или даже невозможно сделать надежно) или просто отрицать возможность (генерировать исключение). Последний из которых, очевидно, является безопасным.

Во втором варианте можно вносить изменения в исходную коллекцию, не беспокоясь о последовательности итераций. Но никаких корректировок в итерации не будет видно, это может сбить с толку пользователей (дырявая абстракция).

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

0
ответ дан 8 December 2019 в 12:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: