Saif
Saif

Reputation: 163

Create array with non-integer increments

I am trying to create time stamp arrays in Swift.

So, say I want to go from 0 to 4 seconds, I can use Array(0...4), which gives [0, 1, 2, 3, 4]

But how can I get [0.0, 0.5 1.0, 2.0, 2.5, 3.0, 3.5, 4.0]?

Essentially I want a flexible delta, such as 0.5, 0.05, etc.

Upvotes: 2

Views: 727

Answers (2)

dfrib
dfrib

Reputation: 73186

An alternative for non-constant increments (even more viable in Swift 3.1)

The stride(from:through:by:) functions as covered in @Alexander's answer is the fit for purpose solution where, but for the case where readers of this Q&A wants to construct a sequence (/collection) of non-constant increments (in which case the linear-sequence constructing stride(...) falls short), I'll also include another alternative.

For such scenarios, the sequence(first:next:) is a good method of choice; used to construct a lazy sequence that can be repeatedly queried for the next element.

E.g., constructing the first 5 ticks for a log10 scale (Double array)

let log10Seq = sequence(first: 1.0, next: { 10*$0 })
let arr = Array(log10Seq.prefix(5)) // [1.0, 10.0, 100.0, 1000.0, 10000.0]

Swift 3.1 is intended to be released in the spring of 2017, and with this (among lots of other things) comes the implementation of the following accepted Swift evolution proposal:

prefix(while:) in combination with sequence(first:next) provides a neat tool for generating sequences with everything for simple next methods (such as imitating the simple behaviour of stride(...)) to more advanced ones. The stride(...) example of this question is a good minimal (very simple) example of such usage:

/* this we can do already in Swift 3.0 */
let delta = 0.05
let seq = sequence(first: 0.0, next: { $0 + delta})

/* 'prefix(while:)' soon available in Swift 3.1 */
let arr = Array(seq.prefix(while: { $0 <= 4.0 }))
    // [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]

// ...
for elem in sequence(first: 0.0, next: { $0 + delta})
    .prefix(while: { $0 <= 4.0 }) {
        // ...
}

Again, not in contest with stride(...) in the simple case of this Q, but very viable as soon as the useful but simple applications of stride(...) falls short, e.g. for a constructing non-linear sequences.

Upvotes: 0

Alexander
Alexander

Reputation: 63281

You can use stride(from:through:by:):

let a = Array(stride(from: 0.0, through: 4.0, by: 0.5))

Upvotes: 7

Related Questions