Как написать следующее в Swift3?
for (f = first; f <= last; f += interval)
{
n += 1
}
Это моя собственная попытка
for _ in 0.stride(to: last, by: interval)
{
n += 1
}
Как написать следующее в Swift3?
for (f = first; f <= last; f += interval)
{
n += 1
}
Это моя собственная попытка
for _ in 0.stride(to: last, by: interval)
{
n += 1
}
Strideable
: s stride(...)
заменен глобальными stride(...)
функциямиВ Swift 2.2 мы можем (как вы пробовали в своей собственной попытке) использовать голубые (и по умолчанию) функции stride(through:by:)
и stride(to:by:)
из протокола Strideable
/* Swift 2.2: stride example usage */ let from = 0 let to = 10 let through = 10 let by = 1 for _ in from.stride(through, by: by) { } // from ... through (steps: 'by') for _ in from.stride(to, by: by) { } // from ..< to (steps: 'by')
В то время как в Swift 3.0 эти две функции были удалены из Strideable
в пользу глобальных функций stride(from:through:by:)
и stride(from:to:by:)
; поэтому эквивалентная версия Swift 3.0 выше следует как
/* Swift 3.0: stride example usage */ let from = 0 let to = 10 let through = 10 let by = 1 for _ in stride(from: from, through: through, by: by) { } for _ in stride(from: from, to: to, by: by) { }
В вашем примере вы хотите использовать альтернативу с интервалом с интервалом stride(from:through:by:)
, так как инвариант в вашем цикле for
использует сравнение с меньшим или равным (<=
). То есть.
/* example values of your parameters 'first', 'last' and 'interval' */
let first = 0
let last = 10
let interval = 2
var n = 0
for f in stride(from: first, through: last, by: interval) {
print(f)
n += 1
} // 0 2 4 6 8 10
print(n) // 6
Где, естественно, мы используем ваш цикл for
только как пример перехода из цикла for
в stride
, как вы можете, естественно, для вашего конкретного примера просто вычислить n
без необходимости цикл (n=1+(last-first)/interval
).
stride
для более сложной итерационной логики увеличенияС помощью реализации эволюционного предложения SE-0094 Swift 3.0 представил глобальные функции sequence
:
которая может быть подходящей альтернативой stride
для случаев с более сложным соотношением приращения итерации (что не так в этом примере).
Декларация (ы)
func sequence<T>(first: T, next: @escaping (T) -> T?) -> UnfoldSequence<T, (T?, Bool)> func sequence<T, State>(state: State, next: @escaping (inout State) -> T?) -> UnfoldSequence<T, State>
Мы кратко рассмотрим первую из этих двух функций. Аргументы next
принимают замыкание, которое применяет некоторую логику для ленивого построения следующего элемента последовательности с учетом текущего (начиная с first
). Последовательность завершается, когда next
возвращает nil
или бесконечно, если a next
никогда не возвращает nil
.
Применительно к приведенному выше примеру с простой степенью, метод sequence
является немного подробным и overkill w.r.t. решение stride
для решения этой задачи:
let first = 0
let last = 10
let interval = 2
var n = 0
for f in sequence(first: first,
next: { $0 + interval <= last ? $0 + interval : nil }) {
print(f)
n += 1
} // 0 2 4 6 8 10
print(n) // 6
Функции sequence
становятся очень полезными для случаев с непостоянным шагом, однако, например, как в примере, приведенном в следующем Q & A:
Просто позаботьтесь о завершении последовательности с последующим возвратом элемента nil
(если нет: "бесконечный" ), или, когда Swift 3.1 прибывает, используйте свое ленивое поколение в сочетании с методом prefix(while:)
для последовательности, как описано в эволюционном предложении SE-0045. Последнее применительно к текущему примеру этого ответа делает подход sequence
менее подробным, в том числе критерии завершения генерации элемента.
/* for Swift 3.1 */
// ... as above
for f in sequence(first: first, next: { $0 + interval })
.prefix(while: { $0 <= last }) {
print(f)
n += 1
} // 0 2 4 6 8 10
print(n) // 6
С Swift 5 вы можете выбрать один из 5 следующих примеров, чтобы решить вашу проблему.
stride(from:to:by:)
let first = 0
let last = 10
let interval = 2
let sequence = stride(from: first, to: last, by: interval)
for element in sequence {
print(element)
}
/*
prints:
0
2
4
6
8
*/
sequence(first:next:)
let first = 0
let last = 10
let interval = 2
let unfoldSequence = sequence(first: first, next: {
$0 + interval < last ? $0 + interval : nil
})
for element in unfoldSequence {
print(element)
}
/*
prints:
0
2
4
6
8
*/
AnySequence
init(_:)
инициализатораlet anySequence = AnySequence<Int>({ () -> AnyIterator<Int> in
let first = 0
let last = 10
let interval = 2
var value = first
return AnyIterator<Int> {
defer { value += interval }
return value < last ? value : nil
}
})
for element in anySequence {
print(element)
}
/*
prints:
0
2
4
6
8
*/
filter(_:)
CountableRange
filter(_:)
методlet first = 0
let last = 10
let interval = 2
let range = first ..< last
let lazyCollection = range.lazy.filter({ $0 % interval == 0 })
for element in lazyCollection {
print(element)
}
/*
prints:
0
2
4
6
8
*/
CountableRange
flatMap(_:)
методlet first = 0
let last = 10
let interval = 2
let range = first ..< last
let lazyCollection = range.lazy.compactMap({ $0 % interval == 0 ? $0 : nil })
for element in lazyCollection {
print(element)
}
/*
prints:
0
2
4
6
8
*/
Просто рабочий код для Swift 3.0:
let (first, last, interval) = (0, 100, 1)
var n = 0
for _ in stride(from: first, to: last, by: interval) {
n += 1
}
для _ в 0.stride(до: last, by: interval) { n + = 1 }