Skip to content

Latest commit

 

History

History
70 lines (50 loc) · 2.34 KB

Stride.md

File metadata and controls

70 lines (50 loc) · 2.34 KB

Stride

[Source | Tests]

Step over the elements of a sequence elements by a specified amount.

This is available through the striding(by:) method on any Sequence.

(0...10).striding(by: 2) // == [0, 2, 4, 6, 8, 10]

If the stride is larger than the length of the sequence, the resulting wrapper only contains the first element.

The stride amount must be a positive value.

Detailed Design

The striding(by:) method is declared in extension of both Sequence and Collection:

extension Sequence {
    public func striding(by step: Int) -> StridingSequence<Self>
}

extension Collection {
    public func striding(by step: Int) -> StridingCollection<Self>
}

The reason for this distinction is subtle. The StridingSequence.Iterator type is unable to skip over multiple elements of the wrapped iterator at once since that's not part of IteratorProtocol's interface. In order to efficiently stride over collections that provide a fast way of skipping multiple elements at once, the StridingCollection type was added which does not provide a custom Iterator type and therefore always strides over the underlying collection in the fastest way possible. See the related GitHub issue for more information.

A careful thought was given to the composition of these strides by giving a custom implementation to index(_:offsetBy:limitedBy) which multiplies the offset by the stride amount.

base.index(i.base, offsetBy: distance * stride, limitedBy: base.endIndex)

The following two lines of code are equivalent, including performance:

(0...10).striding(by: 6)
(0...10).striding(by: 2).stride(by: 3)

Complexity

The call to striding(by: k) is always O(1) and access to the next value in the stride is O(1) if the collection conforms to RandomAccessCollection, otherwise O(k).

Comparison with other languages

rust has Strided available in a crate. c++ has std::slice::stride

The semantics of striding described in this documentation are equivalent.