Here's the code I try to make work
struct A {
var x:Int = 0
}
struct B {
var y:Int = 0
}
var c: [String:Any] = [
"a":[A()],
"b":[B()]
]
for (key, value) in c {
let arr = value as! [Any]
}
It just throws exception. The runtime exception is raised when trying to cast Any to [Any].
The main thing I want to achieve is iterate through the elements of Any, if Any is array. To me it was natural to cast Any to [Any], but for some reason it doesn't work. So how can I do this in obvious thing in swift?
I saw some workarounds to cast Any to [A] or [B], but that's not my case, because the array can contain just an arbitrary struct.
You can make use of runtime introspection to inspect whether values in your dictionary are of collection type, and if so, iterate over their children (= elements, for array case), and append these to an actual array of Any, in so letting Swift know some Any values in your dictionary are actually arrays.
/* Example setup */
struct A {
var x: Int
init(_ x: Int) { self.x = x }
}
struct B {
var y: Int
init(_ y: Int) { self.y = y }
}
var c: [String:Any] = [
"a": [A(1), A(2)],
"b": [B(3)],
"c": "JustAString",
"d": A(0)
]
E.g. as follows
/* runtime introspection to extract array values from dictionary */
var commonAnyArr: [[Any]] = []
for (_, value) in c {
if case let m = Mirror(reflecting: value)
where (m.displayStyle ?? .Struct) == .Collection {
let arr = m.children.map { $0.value }
commonAnyArr.append(arr)
}
}
/* resulting array of any arrs, that Swift now recognize as actual arrays */
commonAnyArr.forEach { print($0) }
/* [B(y: 3)]
[A(x: 1), A(x: 2)] */
commonAnyArr.flatten().forEach { print($0) }
/* B(y: 3)
A(x: 1)
A(x: 2) */
Alternatively, use the runtime introspection to construct a new dictionary, containing only the key-value pairs of c where the underlying value wrapped by the Any value is in fact an array (however in the new dictionary explicitly specifying for swift that the values are arrays of Any).
/* runtime introspection to extract array values from dictionary */
var dictOfAnyArrs: [String: [Any]] = [:]
for (key, value) in c {
if case let m = Mirror(reflecting: value)
where (m.displayStyle ?? .Struct) == .Collection {
let arr = m.children.map { $0.value }
dictOfAnyArrs[key] = arr
}
}
/* "remaining" dictionary keys now only with [Arr] values */
for (key, arr) in dictOfAnyArrs {
for element in arr {
print("Do something with element \(element)")
}
print("---")
}
/* Do something with element B(y: 3)
---
Do something with element A(x: 1)
Do something with element A(x: 2)
--- */
Just note that the above could be considered somewhat "hacky" (in the eyes of Swift and its pride in static typing and runtime safety), and possibly mostly interesting more out of a technical aspect rather than to be used in actual production code (I would personally never allow anything like the above in production of my own). Perhaps if you take a step back and look at how you've reached this issue, you could re-work your code and design to not reach a point where you need to resort to runtime hacks.
I'd like a function runningSum on an array of numbers a (or any ordered collection of addable things) that returns an array of the same length where each element i is the sum of all elements in A up to an including i.
Examples:
runningSum([1,1,1,1,1,1]) -> [1,2,3,4,5,6]
runningSum([2,2,2,2,2,2]) -> [2,4,6,8,10,12]
runningSum([1,0,1,0,1,0]) -> [1,1,2,2,3,3]
runningSum([0,1,0,1,0,1]) -> [0,1,1,2,2,3]
I can do this with a for loop, or whatever. Is there a more functional option? It's a little like a reduce, except that it builds a result array that has all the intermediate values.
Even more general would be to have a function that takes any sequence and provides a sequence that's the running total of the input sequence.
The general combinator you're looking for is often called scan, and can be defined (like all higher-order functions on lists) in terms of reduce:
extension Array {
func scan<T>(initial: T, _ f: (T, Element) -> T) -> [T] {
return self.reduce([initial], combine: { (listSoFar: [T], next: Element) -> [T] in
// because we seeded it with a non-empty
// list, it's easy to prove inductively
// that this unwrapping can't fail
let lastElement = listSoFar.last!
return listSoFar + [f(lastElement, next)]
})
}
}
(But I would suggest that that's not a very good implementation.)
This is a very useful general function, and it's a shame that it's not included in the standard library.
You can then generate your cumulative sum by specializing the starting value and operation:
let cumSum = els.scan(0, +)
And you can omit the zero-length case rather simply:
let cumSumTail = els.scan(0, +).dropFirst()
Swift 4
The general sequence case
Citing the OP:
Even more general would be to have a function that takes any sequence
and provides a sequence that's the running total of the input
sequence.
Consider some arbitrary sequence (conforming to Sequence), say
var seq = 1... // 1, 2, 3, ... (CountablePartialRangeFrom)
To create another sequence which is the (lazy) running sum over seq, you can make use of the global sequence(state:next:) function:
var runningSumSequence =
sequence(state: (sum: 0, it: seq.makeIterator())) { state -> Int? in
if let val = state.it.next() {
defer { state.sum += val }
return val + state.sum
}
else { return nil }
}
// Consume and print accumulated values less than 100
while let accumulatedSum = runningSumSequence.next(),
accumulatedSum < 100 { print(accumulatedSum) }
// 1 3 6 10 15 21 28 36 45 55 66 78 91
// Consume and print next
print(runningSumSequence.next() ?? -1) // 120
// ...
If we'd like (for the joy of it), we could condense the closure to sequence(state:next:) above somewhat:
var runningSumSequence =
sequence(state: (sum: 0, it: seq.makeIterator())) {
(state: inout (sum: Int, it: AnyIterator<Int>)) -> Int? in
state.it.next().map { (state.sum + $0, state.sum += $0).0 }
}
However, type inference tends to break (still some open bugs, perhaps?) for these single-line returns of sequence(state:next:), forcing us to explicitly specify the type of state, hence the gritty ... in in the closure.
Alternatively: custom sequence accumulator
protocol Accumulatable {
static func +(lhs: Self, rhs: Self) -> Self
}
extension Int : Accumulatable {}
struct AccumulateSequence<T: Sequence>: Sequence, IteratorProtocol
where T.Element: Accumulatable {
var iterator: T.Iterator
var accumulatedValue: T.Element?
init(_ sequence: T) {
self.iterator = sequence.makeIterator()
}
mutating func next() -> T.Element? {
if let val = iterator.next() {
if accumulatedValue == nil {
accumulatedValue = val
}
else { defer { accumulatedValue = accumulatedValue! + val } }
return accumulatedValue
}
return nil
}
}
var accumulator = AccumulateSequence(1...)
// Consume and print accumulated values less than 100
while let accumulatedSum = accumulator.next(),
accumulatedSum < 100 { print(accumulatedSum) }
// 1 3 6 10 15 21 28 36 45 55 66 78 91
The specific array case: using reduce(into:_:)
As of Swift 4, we can use reduce(into:_:) to accumulate the running sum into an array.
let runningSum = arr
.reduce(into: []) { $0.append(($0.last ?? 0) + $1) }
// [2, 4, 6, 8, 10, 12]
By using reduce(into:_:), the [Int] accumulator will not be copied in subsequent reduce iterations; citing the Language reference:
This method is preferred over reduce(_:_:) for efficiency when the
result is a copy-on-write type, for example an Array or a
Dictionary.
See also the implementation of reduce(into:_:), noting that the accumulator is provided as an inout parameter to the supplied closure.
However, each iteration will still result in an append(_:) call on the accumulator array; amortized O(1) averaged over many invocations, but still an arguably unnecessary overhead here as we know the final size of the accumulator.
Because arrays increase their allocated capacity using an exponential
strategy, appending a single element to an array is an O(1) operation
when averaged over many calls to the append(_:) method. When an array
has additional capacity and is not sharing its storage with another
instance, appending an element is O(1). When an array needs to
reallocate storage before appending or its storage is shared with
another copy, appending is O(n), where n is the length of the array.
Thus, knowing the final size of the accumulator, we could explicitly reserve such a capacity for it using reserveCapacity(_:) (as is done e.g. for the native implementation of map(_:))
let runningSum = arr
.reduce(into: [Int]()) { (sums, element) in
if let sum = sums.last {
sums.append(sum + element)
}
else {
sums.reserveCapacity(arr.count)
sums.append(element)
}
} // [2, 4, 6, 8, 10, 12]
For the joy of it, condensed:
let runningSum = arr
.reduce(into: []) {
$0.append(($0.last ?? ($0.reserveCapacity(arr.count), 0).1) + $1)
} // [2, 4, 6, 8, 10, 12]
Swift 3: Using enumerated() for subsequent calls to reduce
Another Swift 3 alternative (with an overhead ...) is using enumerated().map in combination with reduce within each element mapping:
func runningSum(_ arr: [Int]) -> [Int] {
return arr.enumerated().map { arr.prefix($0).reduce($1, +) }
} /* thanks #Hamish for improvement! */
let arr = [2, 2, 2, 2, 2, 2]
print(runningSum(arr)) // [2, 4, 6, 8, 10, 12]
The upside is you wont have to use an array as the collector in a single reduce (instead repeatedly calling reduce).
Just for fun: The running sum as a one-liner:
let arr = [1, 2, 3, 4]
let rs = arr.map({ () -> (Int) -> Int in var s = 0; return { (s += $0, s).1 } }())
print(rs) // [1, 3, 6, 10]
It does the same as the (updated) code in JAL's answer, in particular,
no intermediate arrays are generated.
The sum variable is captured in an immediately-evaluated closure returning the transformation.
If you just want it to work for Int, you can use this:
func runningSum(array: [Int]) -> [Int] {
return array.reduce([], combine: { (sums, element) in
return sums + [element + (sums.last ?? 0)]
})
}
If you want it to be generic over the element type, you have to do a lot of extra work declaring the various number types to conform to a custom protocol that provides a zero element, and (if you want it generic over both floating point and integer types) an addition operation, because Swift doesn't do that already. (A future version of Swift may fix this problem.)
Assuming an array of Ints, sounds like you can use map to manipulate the input:
let arr = [0,1,0,1,0,1]
var sum = 0
let val = arr.map { (sum += $0, sum).1 }
print(val) // "[0, 1, 1, 2, 2, 3]\n"
I'll keep working on a solution that doesn't use an external variable.
I thought I'd be cool to extend Sequence with a generic scan function as is suggested in the great first answer.
Given this extension, you can get the running sum of an array like this: [1,2,3].scan(0, +)
But you can also get other interesting things…
Running product: array.scan(1, *)
Running max: array.scan(Int.min, max)
Running min: array.scan(Int.max, min)
Because the implementation is a function on Sequence and returns a Sequence, you can chain it together with other sequence functions. It is efficient, having linear running time.
Here's the extension…
extension Sequence {
func scan<Result>(_ initialResult: Result, _ nextPartialResult: #escaping (Result, Self.Element) -> Result) -> ScanSequence<Self, Result> {
return ScanSequence(initialResult: initialResult, underlying: self, combine: nextPartialResult)
}
}
struct ScanSequence<Underlying: Sequence, Result>: Sequence {
let initialResult: Result
let underlying: Underlying
let combine: (Result, Underlying.Element) -> Result
typealias Iterator = ScanIterator<Underlying.Iterator, Result>
func makeIterator() -> Iterator {
return ScanIterator(previousResult: initialResult, underlying: underlying.makeIterator(), combine: combine)
}
var underestimatedCount: Int {
return underlying.underestimatedCount
}
}
struct ScanIterator<Underlying: IteratorProtocol, Result>: IteratorProtocol {
var previousResult: Result
var underlying: Underlying
let combine: (Result, Underlying.Element) -> Result
mutating func next() -> Result? {
guard let nextUnderlying = underlying.next() else {
return nil
}
previousResult = combine(previousResult, nextUnderlying)
return previousResult
}
}
One solution using reduce:
func runningSum(array: [Int]) -> [Int] {
return array.reduce([], combine: { (result: [Int], item: Int) -> [Int] in
if result.isEmpty {
return [item] //first item, just take the value
}
// otherwise take the previous value and append the new item
return result + [result.last! + item]
})
}
I'm very late to this party. The other answers have good explanations. But none of them have provided the initial result, in a generic way. This implementation is useful to me.
public extension Sequence {
/// A sequence of the partial results that `reduce` would employ.
func scan<Result>(
_ initialResult: Result,
_ nextPartialResult: #escaping (Result, Element) -> Result
) -> AnySequence<Result> {
var iterator = makeIterator()
return .init(
sequence(first: initialResult) { partialResult in
iterator.next().map {
nextPartialResult(partialResult, $0)
}
}
)
}
}
extension Sequence where Element: AdditiveArithmetic & ExpressibleByIntegerLiteral {
var runningSum: AnySequence<Element> { scan(0, +).dropFirst() }
}
I need to efficiently aggregate an array of non-optional values, knowing its size, having a way to get its values, but not having a default value.
Following is a rather synthetic example, resembling what I need. It won't compile, but it will give you the idea:
public func array<A>( count: Int, getValue: () -> A ) -> Array<A> {
var array = [A](count: count, repeatedValue: nil as! A)
var i = 0
while (i < count) {
array[i] = getValue()
i++
}
return array
}
Please note that the result of type Array<A?> won't do, I need non-optionals. Also note that the solution must be efficient, it must not do any extra traversals.
You can make a working function from your example code by using
the append() method to add array elements:
public func array<A>(count: Int, #noescape getValue: () -> A) -> [A] {
var array = [A]()
array.reserveCapacity(count)
for _ in 0 ..< count {
array.append(getValue())
}
return array
}
The #noescape
attribute tells the compiler that the passed closure does not outlive
the function call, this allows some performance optimizations,
compare #noescape attribute in Swift 1.2.
But it is easier to use the map() method of CollectionType:
/// Return an `Array` containing the results of mapping `transform`
/// over `self`.
///
/// - Complexity: O(N).
#warn_unused_result
public func map<T>(#noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
In your case:
public func array<A>(count: Int, #noescape getValue: () -> A) -> [A] {
let array = (0 ..< count).map { _ in getValue() }
return array
}
Here map() transforms each integer in the range 0 ... count-1
to an array element. The underscore in the closure indicates that
its argument (the current index) is not used.
I leave it to you to check which method is faster.
Example usage:
let a = array(10) { arc4random_uniform(10) }
print(a) // [3, 7, 9, 4, 2, 3, 1, 5, 9, 7] (Your output may be different :-)
As an exercise, I'm implementing a map function that takes an array and a function and applies the function to all elements of the array, but I don't know how to declare it such that it works for any type of array.
I can do something like
func intMap(var arr: [Int], fun: (Int) -> Int) -> [Int] {
for i in 0 ..< arr.count {
arr[i] = fun(arr[i])
}
return arr
}
intMap([1,2,3], {x in return x * x})
But this only works for int.
What is the type signature for Swift's built-in map?
Edit:
So I was missing the fact that I can declare param type signatures without declaring their types explicitly.
func myMap<T>(var arr: [T], fun: (T) -> T) -> [T] {
for i in 0 ..< arr.count {
arr[i] = fun(arr[i])
}
return arr
}
myMap([1,2,3], fun: {
x in return x * x
})
Create a new Playground
Just under where it has import UIKit type import Swift
Command click on the word Swift
This will open the Swift library and you can see all the type definitions there.
And you can see:
extension CollectionType {
/// Return an `Array` containing the results of mapping `transform`
/// over `self`.
///
/// - Complexity: O(N).
#warn_unused_result
#rethrows public func map<T>(#noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
Edited to add
Alternatively, you can write a more generalised map
func myMap<T, U>(var arr: [T], fun: T -> U) -> [U] {
var a: [U] = []
for i in 0 ..< arr.count {
a.append(fun(arr[i]))
}
return a
}
Which returns a new array, of a possibly different type, which you can see for yourself by putting this in your playground.
let a = [1, 2, 3]
let b = myMap(a, fun: { x in Double(x) * 2.1 })
a
b
I'd like to write an extension for tuples of (e.g.) two value in Swift. For instance, I'd like to write this swap method:
let t = (1, "one")
let s = t.swap
such that s would be of type (String, Int) with value ("one", 1). (I know I can very easily implement a swap(t) function instead, but that's not what I'm interested in.)
Can I do this? I cannot seem to write the proper type name in the extension declaration.
Additionally, and I suppose the answer is the same, can I make a 2-tuple adopt a given protocol?
You cannot extend tuple types in Swift.
According to
Types, there are named types (which
can be extended) and compound types. Tuples and functions are compound
types.
See also (emphasis added):
Extensions
Extensions add new functionality to an existing
class, structure, or enumeration type.
As the answer above states, you cannot extend tuples in Swift. However, rather than just give you a no, what you can do is box the tuple inside a class, struct or enum and extend that.
struct TupleStruct {
var value: (Int, Int)
}
extension TupleStruct : Hashable {
var hashValue: Int {
return hash()
}
func hash() -> Int {
var hash = 23
hash = hash &* 31 &+ value.0
return hash &* 31 &+ value.1
}
}
func ==(lhs: TupleStruct, rhs: TupleStruct) -> Bool {
return lhs.value == rhs.value
}
As a side note, in Swift 2.2, tuples with up to 6 members are now Equatable.
Details
Xcode 11.2.1 (11B500), Swift 5.1
Solution
struct Tuple<T> {
let original: T
private let array: [Mirror.Child]
init(_ value: T) {
self.original = value
array = Array(Mirror(reflecting: original).children)
}
func getAllValues() -> [Any] { array.compactMap { $0.value } }
func swap() -> (Any?, Any?)? {
if array.count == 2 { return (array[1].value, array[0].value) }
return nil
}
}
Usage
let x = (1, "one")
let tuple = Tuple(x)
print(x) // (1, "one")
print(tuple.swap()) // Optional((Optional("one"), Optional(1)))
if let value = tuple.swap() as? (String, Int) {
print("\(value) | \(type(of: value))") // ("one", 1) | (String, Int)
}
If you wanted to be a Bad Person™ you can define custom operators on tuples, like this:
postfix operator <->
postfix func <-> <A, B>(lhs: (A, B)) -> (B, A) {
return (lhs.1, lhs.0)
}
let initial = (1, "one")
let reversed = initial<->
FWIW I can't think of a place where my 'clever' code trumps the readability of just writing your swap function.