NumPy | ArraySliceWithStride | Result | |
---|---|---|---|
Array creation | a = np.array(range(0,10)) |
var a = Array(0..<10) |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] |
All sliced | a[:] |
a[.|1] |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] |
Sliced by 2 | a[::2] |
a[.|2] |
[0, 2, 4, 6, 8] |
Sliced from 2 | a[2:] |
a[2.~] |
[2, 3, 4, 5, 6, 7, 8, 9] |
Sliced to the 2nd last index (-2) | a[:-2] |
a[.~(-2)] |
[0, 1, 2, 3, 4, 5, 6, 7] |
Sliced from 2 to -2 | a[2:-2] |
a[2.~(-2)] |
[2, 3, 4, 5, 6, 7] |
Sliced from 2 by 3 | a[2::3] |
a[2.~ .| 3] |
[2, 5, 8] |
Sliced to -2 by 3 | a[:-2:3] |
a[.~(-2).|3] |
[0, 3, 6] |
Sliced from 2 to -2 by 3 | a[2:-2:3] |
a[2.~(-2).|3] |
[2, 5] |
Storing the array sliced by 2 in the first 5 places | a[:5] = a[::2] |
a[.~5] = a[.|2] |
[0, 2, 4, 6, 8, 5, 6, 7, 8, 9] |
Element-wise addition | a[::2] + a[1::2] |
a[.|2].zip(a[1.~ .| 2], map: +) |
[1, 5, 9, 13, 17] |
Element-wise subtraction | a[::2] - a[1::2] |
a[.|2].zip(a[1.~ .| 2], map: -) |
[-1, -1, -1, -1, -1] |
Element-wise multiplication | a[::2] * a[1::2] |
a[.|2].zip(a[1.~ .| 2], map: *) |
[0, 6, 20, 42, 72] |
Element-wise division | a[3::2] / a[2::2] |
a[3.~ .| 2].zip(a[2.~ .| 2], map: /) |
[1, 1, 1, 1] |
Element-wise square | a[::2]**2 |
a[.|2].map({$0*$0}) |
[0, 4, 16, 36, 64] |
Maximum | a[:-2:2].max() |
a[.~(-2).|2].reduce(Int.min, max) |
6 |
Minimun | a[2::2].min() |
a[2.~ .| 2].reduce(Int.max, min) |
2 |
Sum | a[2::2].sum() |
a[2.~ .| 2].reduce(0, +) |
20 |
Product | a[2::2].prod() |
a[2.~ .| 2].reduce(1, *) |
384 |
Last active
July 9, 2018 05:16
-
-
Save Tony-Y/40fa7fcc069ed5337e1a02c12d937287 to your computer and use it in GitHub Desktop.
ArraySliceWithStride: a[start .~ end .| step]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct ArraySliceWithStride<Element> { | |
typealias Base = Array<Element> | |
private let _base: Base | |
private let _slice: Array<Any>.Slice | |
private var _start: Int { return _slice.start! } | |
let count: Int | |
private var _stride: Int { return _slice.stride } | |
init(_ base: Base, from start: Base.Index?, to end: Base.Index?, by stride: Base.Index.Stride) { | |
self._base = base | |
self._slice = Array.Slice(from: start, to: end, by: stride).relative(to: base) | |
self.count = self._slice.count | |
} | |
} | |
extension ArraySliceWithStride { | |
subscript (position: Int) -> Element { | |
get { | |
return _base[_start + position * _stride] | |
} | |
} | |
func iterator() -> AnyIterator<Element> { | |
var position = _start | |
return AnyIterator<Element>({ | |
defer { position += self._stride } | |
return self._base[position] | |
}) | |
} | |
func map<T>(_ transform: (Element) throws -> T) rethrows -> ArraySliceWithStride<T> { | |
var array = [T]() | |
array.reserveCapacity(count) | |
let iter = self.iterator() | |
for _ in 0..<count { | |
array.append(try transform(iter.next()!)) | |
} | |
return array.allSliced() | |
} | |
func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result { | |
var result = initialResult | |
let iter = self.iterator() | |
for _ in 0..<count { | |
result = try nextPartialResult(result, iter.next()!) | |
} | |
return result | |
} | |
func zip<T>(_ array2: ArraySliceWithStride<Element>, map transform: (Element, Element) throws -> T) rethrows -> ArraySliceWithStride<T> { | |
var array = [T]() | |
let minCount = min(self.count, array2.count) | |
array.reserveCapacity(minCount) | |
let iter1 = self.iterator() | |
let iter2 = array2.iterator() | |
for _ in 0..<minCount { | |
array.append(try transform(iter1.next()!, iter2.next()!)) | |
} | |
return array.allSliced() | |
} | |
} | |
extension ArraySliceWithStride : CustomStringConvertible { | |
var description: String { | |
var text = "" | |
//text += "count: \(count) start: \(_start) stride: \(_stride)\n" | |
if count > 0 { | |
text += "[\(self[0])" | |
for i in 1..<count { | |
text += ", \(self[i])" | |
} | |
text += "]" | |
} else { | |
text += "[]" | |
} | |
return text | |
} | |
} | |
precedencegroup SliceFormationPrecedence { | |
associativity: left | |
lowerThan: AdditionPrecedence | |
} | |
infix operator .~: SliceFormationPrecedence | |
prefix operator .~ | |
postfix operator .~ | |
infix operator .|: SliceFormationPrecedence | |
prefix operator .| | |
func .~ (lhs: Int, rhs: Int) -> Array<Any>.Slice { | |
return Array.Slice(from: lhs, to: rhs, by: 1) | |
} | |
prefix func .~ (rhs: Int) -> Array<Any>.Slice { | |
return Array.Slice(from: nil, to: rhs, by: 1) | |
} | |
postfix func .~ (lhs: Int) -> Array<Any>.Slice { | |
return Array.Slice(from: lhs, to: nil, by: 1) | |
} | |
func .| (lhs: Array<Any>.Slice, rhs: Int) -> Array<Any>.Slice { | |
return Array.Slice(from: lhs.start, to: lhs.end, by: rhs * lhs.stride) | |
} | |
prefix func .| (rhs: Int) -> Array<Any>.Slice { | |
return Array.Slice(from: nil, to: nil, by: rhs) | |
} | |
extension Array { | |
struct Slice { | |
var start: Int? | |
var end: Int? | |
var stride: Int | |
init(from start: Int?, to end: Int?, by stride: Int) { | |
guard stride != 0 else { | |
fatalError("Stride size must not be zero") | |
} | |
self.start = start | |
self.end = end | |
self.stride = stride | |
} | |
var count: Int { | |
guard let start = start else { return 0 } | |
guard let end = end else { return 0 } | |
let offset = stride > 0 ? stride - 1 : stride + 1 | |
return (end - start + offset) / stride | |
} | |
func relative(to array: Array<Element>) -> Array<Any>.Slice { | |
var start: Int | |
var end: Int | |
if self.stride > 0 { | |
start = self.start ?? array.startIndex | |
if start < 0 { start = array.endIndex + start } | |
if start < array.startIndex { start = array.startIndex } | |
end = self.end ?? array.endIndex | |
if end < 0 { end = array.endIndex + end } | |
if end > array.endIndex { end = array.endIndex } | |
if start > end { | |
fatalError("Start must not be more than End for positive Stride") | |
} | |
} else { | |
let arrayStart = array.endIndex.advanced(by: -1) | |
start = self.start ?? arrayStart | |
if start < 0 { start = array.endIndex + start } | |
if start > arrayStart { start = arrayStart } | |
let arrayEnd = array.startIndex.advanced(by: -1) | |
if let stop = self.end { | |
if stop < 0 { end = array.endIndex + stop } else { end = stop } | |
} else { | |
end = arrayEnd | |
} | |
if end < arrayEnd { end = arrayEnd } | |
if start < end { | |
fatalError("Start must not be less than End for negative Stride") | |
} | |
} | |
return Array<Any>.Slice(from: start, to: end, by: self.stride) | |
} | |
} | |
func sliced(from start: Index? = nil, to end: Index? = nil, by stride: Index.Stride) -> ArraySliceWithStride<Element> { | |
return ArraySliceWithStride(self, from: start, to: end, by: stride) | |
} | |
func allSliced() -> ArraySliceWithStride<Element> { | |
return ArraySliceWithStride(self, from: self.startIndex, to: self.endIndex, by: 1) | |
} | |
subscript (slice: Array<Any>.Slice) -> ArraySliceWithStride<Element> { | |
get { | |
return ArraySliceWithStride<Element>(self, from: slice.start, to: slice.end, by: slice.stride) | |
} | |
set { | |
let slice = slice.relative(to: self) | |
var position = slice.start! | |
let iter = newValue.iterator() | |
for _ in 0..<Swift.min(slice.count, newValue.count) { | |
self[position] = iter.next()! | |
position += slice.stride | |
} | |
} | |
} | |
} | |
// For example: | |
/* | |
var array1 = Array<Int32>(0..<10) | |
print(array1) | |
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
let view1 = array1.sliced(from: 2, to: 10, by: 2) | |
print(view1) | |
// [2, 4, 6, 8] | |
print(view1.reduce(0, +)) | |
// 20 | |
let view2 = array1[2.~ .| 2] | |
print(view2) | |
// [2, 4, 6, 8] | |
let view3 = array1[(-1).~ .| -3] | |
print(view3) | |
// [9, 6, 3, 0] | |
print(array1[1.~ .| 2].zip(array1[2.~ .| 2], map: +)) | |
// [3, 7, 11, 15] | |
array1[1.~ .| 2] = array1[2.~ .| 2].map({$0*$0}) | |
print(array1) | |
// [0, 4, 2, 16, 4, 36, 6, 64, 8, 9] | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Stride Operators in Swift Forums.