Когда я использую цикл for в Playground, все работало нормально, пока я не изменил первый параметр цикла for на самое высокое значение. (повторяется в порядке убывания)
Это ошибка? У кого-нибудь еще это было?
for index in 510..509
{
var a = 10
}
Счетчик, который отображает количество итераций, которые будут выполняться, продолжает тикать ...
ios
swift
swift-playground
Кришнан
источник
источник
Ответы:
В Xcode 6 beta 4 добавлены две функции для итерации по диапазонам с шагом, отличным от одного:,
stride(from: to: by:)
который используется с исключительными диапазонами иstride(from: through: by:)
который используется с включающими диапазонами.Для итерации диапазона в обратном порядке их можно использовать, как показано ниже:
Обратите внимание, что ни один из них не является
Range
функцией-членом. Это глобальные функции, которые возвращают aStrideTo
илиStrideThrough
struct, которые определены не так, какRange
struct.Предыдущая версия этого ответа использовала
by()
функцию-членRange
структуры, которая была удалена в бета-версии 4. Если вы хотите увидеть, как это работает, проверьте историю редактирования.источник
5.stride(to: 1, by: -1)
или5.stride(through: 1, by: -1)
:
оператор неявно выполняет итерацию вниз, заставляя их циклы выполняться, когда они думают, что они пропустят их. Это очень удобно для интерактивного использования, но ужасно подвержено ошибкам в сценариях до такой степени, что руководства по стилю рекомендуют не использовать его .Примените функцию реверса к диапазону для итерации в обратном направлении:
Для Swift 1.2 и более ранних версий:
Он также работает с полуоткрытыми диапазонами:
Примечание:
reverse(1...10)
создает массив типа[Int]
, поэтому, хотя это может быть хорошо для небольших диапазонов, было бы целесообразно использовать,lazy
как показано ниже, или рассмотреть принятыйstride
ответ, если ваш диапазон большой.Чтобы избежать создания большого массива, используйте
lazy
вместе сreverse()
. Следующий тест эффективно работает на игровой площадке, показывая, что он не создает массив с одним триллиономInt
с!Тест:
Для Swift 2.0 в Xcode 7:
Обратите внимание, что в Swift 2.0,
(1...1_000_000_000_000).reverse()
это типReverseRandomAccessCollection<(Range<Int>)>
, так что это прекрасно работает:Для Swift 3.0
reverse()
был переименован вreversed()
:источник
reversed
может скопировать коллекцию, хотя. По крайней мере, так я понимаю документациюData
.Обновлено для Swift 3
Ответ ниже представляет собой сводку доступных опций. Выберите тот, который наилучшим образом соответствует вашим потребностям.
reversed
: числа в диапазонеВперед
назад
reversed
: элементы вSequenceType
Вперед
назад
reversed
: элементы с индексомИногда требуется индекс для итерации по коллекции. Для этого вы можете использовать
enumerate()
, который возвращает кортеж. Первый элемент кортежа - это индекс, а второй элемент - это объект.Вперед
назад
Обратите внимание, что, как отметил Бен Лахман в своем ответе , вы, скорее всего, захотите сделать это,
.enumerated().reversed()
а не.reversed().enumerated()
(что приведет к увеличению числа индексов).шагать: цифры
Stride - это способ итерации без использования диапазона. Есть две формы. Комментарии в конце кода показывают, какой будет версия диапазона (при условии, что размер приращения равен 1).
Вперед
назад
Изменение размера приращения
-1
позволяет вам вернуться назад.Обратите внимание , что
to
иthrough
различие.шаг: элементы SequenceType
Вперед с шагом 2
Я использую
2
в этом примере, чтобы показать еще одну возможность.назад
Ноты
У @matt есть интересное решение, в котором он определяет свой собственный оператор реверса и вызывает его
>>>
. Для определения не требуется много кода, и он используется так:Проверьте на C-Style для петель, удаленных из Swift 3
источник
Свифт 4 года
источник
С Swift 5, в соответствии с вашими потребностями, вы можете выбрать один из четырех следующих примеров кода Playground , чтобы решить вашу проблему.
# 1. Используя
ClosedRange
reversed()
методClosedRange
имеет метод с именемreversed()
.reversed()
Метод имеет следующую декларацию:Использование:
В качестве альтернативы вы можете использовать
Range
reversed()
метод:# 2. Используя
sequence(first:next:)
функциюСтандартная библиотека Swift предоставляет функцию с именем
sequence(first:next:)
.sequence(first:next:)
имеет следующую декларацию:Использование:
# 3. Используя
stride(from:through:by:)
функциюСтандартная библиотека Swift предоставляет функцию с именем
stride(from:through:by:)
.stride(from:through:by:)
имеет следующую декларацию:Использование:
В качестве альтернативы вы можете использовать
stride(from:to:by:)
:# 4. Использование
AnyIterator
init(_:)
инициализатораAnyIterator
имеет инициализатор под названиемinit(_:)
.init(_:)
имеет следующую декларацию:Использование:
При необходимости вы можете изменить рефакторинг предыдущего кода, создав метод расширения
Int
и обернув в него свой итератор:источник
Для Swift 2.0 и выше вы должны применить реверс на коллекцию диапазонов
Он был переименован в .reversed () в Swift 3.0
источник
В Swift 4 и последних
источник
Swift 4.0
Если вы хотите включить
to
значение:источник
Если кто-то хочет перебрать массив (
Array
или, вообще говоря, любойSequenceType
) в обратном порядке. У вас есть несколько дополнительных опций.Сначала вы можете
reverse()
массива и цикл через него, как обычно. Однако я предпочитаю использоватьenumerate()
большую часть времени, так как он выводит кортеж, содержащий объект и его индекс.Здесь нужно отметить одну вещь: важно называть их в правильном порядке:
for (index, element) in array.enumerate().reverse()
дает индексы в порядке убывания (что я обычно ожидаю). в то время как:
for (index, element) in array.reverse().enumerate()
(что ближе к NSArrayreverseEnumerator
)идет назад по массиву, но выводит восходящие индексы.
источник
как для Swift 2.2, Xcode 7.3 (10 июня 2016 г.):
Вывод :
источник
while
Вместо этого вы можете использовать цикл C-Style . Это прекрасно работает в Swift 3:источник
Вы можете использовать метод reversed () для легкого реверсирования значений.
Метод reversed () меняет значения.
источник
источник