Как повторить цикл for в обратном порядке в swift?
когда я использую цикл for В Playground, все работало нормально, пока я не изменил первый параметр цикла for на самое высокое значение. (повторяется в порядке убывания)
это ошибка? У кого-нибудь еще она была?
for index in 510..509
{
var a = 10
}
счетчик, отображающий количество итераций, которые будут выполняться, продолжает тикать...
13 ответов:
Xcode 6 beta 4 добавлены две функции для итерации по диапазонам с шагом, отличным от одного:
stride(from: to: by:)
, который используется с эксклюзивными диапазонами иstride(from: through: by:)
, который используется при включение диапазонов.выполнить итерации по ряду в обратном порядке, они могут быть использованы, как показано ниже:
for index in stride(from: 5, to: 1, by: -1) { print(index) } //prints 5, 4, 3, 2 for index in stride(from: 5, through: 1, by: -1) { print(index) } //prints 5, 4, 3, 2, 1
обратите внимание, что ни один из них не является
Range
функции-члена. Это глобальные функции, которые возвращают либо aStrideTo
илиStrideThrough
структуры, которые определяются иначе, чемRange
структура.в предыдущей версии этого ответа использовался
by()
функции-членаRange
структура, которая была удалена в бета-версии 4. Если вы хотите увидеть, как это работает, проверьте историю правок.
применить обратную функцию к диапазону, чтобы выполнить итерации в обратном направлении:
на Swift 1.2 и ранее:
// Print 10 through 1 for i in reverse(1...10) { println(i) }
он также работает с полуоткрытым диапазоны:
// Print 9 through 1 for i in reverse(1..<10) { println(i) }
Примечание:
reverse(1...10)
создает массив типа[Int]
, так как это может быть хорошо для небольших диапазонов, было бы разумно использоватьlazy
, как показано ниже, или считать принятымstride
ответьте, если ваш диапазон большой.
чтобы избежать создания большого массив, используйте
lazy
вместе сreverse()
. Следующий тест выполняется эффективно на игровой площадке, показывая, что он не создает массив с одним триллиономInt
s!
обновлено для Swift 3
ответ ниже представляет собой резюме доступных вариантов. Выберите тот, который лучше всего соответствует вашим потребностям.
reversed
: числа в диапазоневперед
for index in 0..<5 { print(index) } // 0 // 1 // 2 // 3 // 4
назад
for index in (0..<5).reversed() { print(index) } // 4 // 3 // 2 // 1 // 0
reversed
: элементыSequenceType
let animals = ["horse", "cow", "camel", "sheep", "goat"]
вперед
for animal in animals { print(animal) } // horse // cow // camel // sheep // goat
назад
for animal in animals.reversed() { print(animal) } // goat // sheep // camel // cow // horse
reversed
: элементы с индексоминогда индекс необходим при итерации по коллекции. Для этого вы можете использовать
enumerate()
, который возвращает кортеж. Первый элемент кортежа-это индекс, а второй элемент - объект.let animals = ["horse", "cow", "camel", "sheep", "goat"]
вперед
for (index, animal) in animals.enumerated() { print("\(index), \(animal)") } // 0, horse // 1, cow // 2, camel // 3, sheep // 4, goat
назад
for (index, animal) in animals.enumerated().reversed() { print("\(index), \(animal)") } // 4, goat // 3, sheep // 2, camel // 1, cow // 0, horse
обратите внимание, что, как отметил Бен Лахман в ответ, вы, наверное, хотите сделать
.enumerated().reversed()
, а не.reversed().enumerated()
(что приведет к увеличению индексов).шаг: цифры
Stride-это способ итерации без использования диапазона. Есть две формы. Комментарии в конце кода показывают какой диапазон версия будет (при условии, что размер инкремент 1).
startIndex.stride(to: endIndex, by: incrementSize) // startIndex..<endIndex startIndex.stride(through: endIndex, by: incrementSize) // startIndex...endIndex
вперед
for index in stride(from: 0, to: 5, by: 1) { print(index) } // 0 // 1 // 2 // 3 // 4
назад
изменение размера доплат к
-1
позволяет вернуться назад.for index in stride(from: 4, through: 0, by: -1) { print(index) } // 4 // 3 // 2 // 1 // 0
Примечание
to
иthrough
разницы.stride: элементы SequenceType
вперед с шагом 2
let animals = ["horse", "cow", "camel", "sheep", "goat"]
я использую
2
в этом пример просто чтобы показать другую возможность.for index in stride(from: 0, to: 5, by: 2) { print("\(index), \(animals[index])") } // 0, horse // 2, camel // 4, goat
назад
for index in stride(from: 4, through: 0, by: -1) { print("\(index), \(animals[index])") } // 4, goat // 3, sheep // 2, camel // 1, cow // 0, horse
Примечания
@matt has интересным решением где он определяет свой собственный оператор реверса и называет это
>>>
. Это не займет много кода, чтобы определить и используется следующим образом:for index in 5>>>0 { print(index) } // 4 // 3 // 2 // 1 // 0
Swift 4 далее
for i in stride(from: 5, to: 0, by: -1) { print(i) } //prints 5, 4, 3, 2, 1 for i in stride(from: 5, through: 0, by: -1) { print(i) } //prints 5, 4, 3, 2, 1, 0
для Swift 2.0 и выше вы должны применить обратный на коллекции диапазона
for i in (0 ..< 10).reverse() { // process }
Он был переименован .обратная() в Swift 3.0
с Swift 3, в соответствии с вашими потребностями, вы можете выбрать один из восемь следующих реализаций кода игровой площадки для того, чтобы решить вашу проблему.
#1. Используя
CountableClosedRange
reversed()
метод
CountableClosedRange
имеет метод под названиемreversed()
.reversed()
метод имеет следующее объявление:func reversed() -> ReversedRandomAccessCollection<CountableClosedRange<Bound>>
возвращает представление, представляющее элементы коллекции в обратном порядке порядок.
использование:
let reversedRandomAccessCollection = (0 ... 5).reversed() for index in reversedRandomAccessCollection { print(index) } /* Prints: 5 4 3 2 1 0 */
#2. Используя
CountableRange
reversed()
метод
CountableRange
имеет метод под названиемreversed()
.reversed()
метод имеет следующее объявление:func reversed() -> ReversedRandomAccessCollection<CountableRange<Bound>>
возвращает представление, представляющее элементы коллекции в обратном порядке.
использование:
let reversedRandomAccessCollection = (0 ..< 6).reversed() for index in reversedRandomAccessCollection { print(index) } /* Prints: 5 4 3 2 1 0 */
#3. Используя
sequence(first:next:)
функциястандартная библиотека Swift предоставляет функцию под названием
sequence(first:next:)
.sequence(first:next:)
есть следующее объявление:func sequence<T>(first: T, next: @escaping (T) -> T?) -> UnfoldSequence<T, (T?, Bool)>
возвращает последовательность, сформированную из
first
и повторные ленивые приложенияnext
.использование:
let unfoldSequence = sequence(first: 5, next: { > 0 ? - 1 : nil }) for index in unfoldSequence { print(index) } /* Prints: 5 4 3 2 1 0 */
#4. Используя
stride(from:through:by:)
функциистандартная библиотека Swift предоставляет функцию под названием
stride(from:through:by:)
.stride(from:through:by:)
есть следующее объявление:func stride<T>(from start: T, through end: T, by stride: T.Stride) -> StrideThrough<T> where T : Strideable
возвращает последовательность значений
(self, self + stride, self + 2 * stride, … last)
где last-последнее значение в прогрессии меньше или равноend
.использование:
let sequence = stride(from: 5, through: 0, by: -1) for index in sequence { print(index) } /* Prints: 5 4 3 2 1 0 */
#5. Используя
stride(from:to:by:)
функциистандартная библиотека Swift предоставляет функцию под названием
stride(from:to:by:)
.stride(from:to:by:)
есть следующее объявление:func stride<T>(from start: T, to end: T, by stride: T.Stride) -> StrideTo<T> where T : Strideable
возвращает последовательность значений
(self, self + stride, self + 2 * stride, … last)
где last-последнее значение в прогрессии, которое меньшеend
.использование:
let sequence = stride(from: 5, to: -1, by: -1) for index in sequence { print(index) } /* Prints: 5 4 3 2 1 0 */
#6. Используя
AnyIterator
init(_:)
инициализатор
AnyIterator
имеет инициализатор под названиемinit(_:)
.init(_:)
есть следующее объявление:init<I>(_ base: I) where I : IteratorProtocol, I.Element == Element
создает итератор, который обертывает базовый итератор, но тип которого зависит только от типа элемента базового итератора.
использование:
var index = 5 guard index >= 0 else { fatalError("index must be positive or equal to zero") } let iterator = AnyIterator<Int>({ defer { index = index - 1 } return index >= 0 ? index : nil }) for index in iterator { print(index) } /* Prints: 5 4 3 2 1 0 */
#7. Используя
AnyIterator
init(_:)
инициализатор
AnyIterator
имеет инициализатор под названиемinit(_:)
.init(_:)
есть следующее объявление:init(_ body: @escaping () -> AnyIterator.Element?)
создает итератор, который обертывает данное закрытие в его
next()
метод.использование:
var index = 5 guard index >= 0 else { fatalError("index must be positive or equal to zero") } let iterator = AnyIterator({ () -> Int? in defer { index = index - 1 } return index >= 0 ? index : nil }) for index in iterator { print(index) } /* Prints: 5 4 3 2 1 0 */
#8. Использование пользовательского
Int
метод расширениявы можете реорганизовать предыдущий код, создав метод расширения для
Int
и обертывание итератора в нем:extension Int { func iterateDownTo(_ endIndex: Int) -> AnyIterator<Int> { var index = self guard index >= endIndex else { fatalError("self must be greater than or equal to endIndex") } let iterator = AnyIterator { () -> Int? in defer { index = index - 1 } return index >= endIndex ? index : nil } return iterator } } let iterator = 5.iterateDownTo(0) for index in iterator { print(index) } /* Prints: 5 4 3 2 1 0 */
Swift 4.0
for i in stride(from: 5, to: 0, by: -1) { print(i) // 5,4,3,2,1 }
Если вы хотите включить
to
значение:for i in stride(from: 5, through: 0, by: -1) { print(i) // 5,4,3,2,1,0 }
если кто-то хочет перебрать массив (
Array
или вообще любойSequenceType
) в обратном направлении. У вас есть несколько дополнительных опций.вы можете
reverse()
массив и цикл через него, как обычно. Однако я предпочитаю использоватьenumerate()
большую часть времени, так как он выводит кортеж, содержащий объект и его индекс.здесь следует отметить, что важно называть их правильно порядок:
for (index, element) in array.enumerate().reverse()
дает индексы в порядке убывания (что я обычно ожидаю). тогда как:
for (index, element) in array.reverse().enumerate()
(который является гораздо ближе к )ходит массив назад, но выводит восходящие индексы.
Что касается Swift 2.2, Xcode 7.3 (10, июнь, 2016):
for (index,number) in (0...10).enumerate() { print("index \(index) , number \(number)") } for (index,number) in (0...10).reverse().enumerate() { print("index \(index) , number \(number)") }
выход :
index 0 , number 0 index 1 , number 1 index 2 , number 2 index 3 , number 3 index 4 , number 4 index 5 , number 5 index 6 , number 6 index 7 , number 7 index 8 , number 8 index 9 , number 9 index 10 , number 10 index 0 , number 10 index 1 , number 9 index 2 , number 8 index 3 , number 7 index 4 , number 6 index 5 , number 5 index 6 , number 4 index 7 , number 3 index 8 , number 2 index 9 , number 1 index 10 , number 0
var sum1 = 0 for i in 0...100{ sum1 += i } print (sum1) for i in (10...100).reverse(){ sum1 /= i } print(sum1)