How to count the number of dimensions in Swift array [duplicate] - swift

Suppose I have some function that I want to populate my data structure using a multi-dimensional array (e.g. a Tensor class):
class Tensor {
init<A>(array:A) { /* ... */ }
}
while I could add in a shape parameter, I would prefer to automatically calculate the dimensions from the array itself. If you know apriori the dimensions, it's trivial to read it off:
let d1 = array.count
let d2 = array[0].count
However, it's less clear how to do it for an N-dimensional array. I was thinking there might be a way to do it by extending the Array class:
extension Int {
func numberOfDims() -> Int {
return 0
}
}
extension Array {
func numberOfDims() -> Int {
return 1+Element.self.numberOfDims()
}
}
Unfortunately, this won't (rightfully so) compile, as numberOfDims isn't defined for most types. However, I'm don't see any way of constraining Element, as Arrays-of-Arrays make things complicated.
I was hoping someone else might have some insight into how to solve this problem (or explain why this is impossible).

If you're looking to get the depth of a nested array (Swift's standard library doesn't technically provide you with multi-dimensional arrays, only jagged arrays) – then, as shown in this Q&A, you can use a 'dummy protocol' and typecasting.
protocol _Array {
var nestingDepth: Int { get }
}
extension Array : _Array {
var nestingDepth: Int {
return 1 + ((first as? _Array)?.nestingDepth ?? 0)
}
}
let a = [1, 2, 3]
print(a.nestingDepth) // 1
let b = [[1], [2, 3], [4]]
print(b.nestingDepth) // 2
let c = [[[1], [2]], [[3]], [[4], [5]]]
print(c.nestingDepth) // 3
(I believe this approach would've still worked when you had originally posted the question)
In Swift 3, this can also be achieved without a dummy protocol, but instead by casting to [Any]. However, as noted in the linked Q&A, this is inefficient as it requires traversing the entire array in order to box each element in an existential container.
Also note that this implementation assumes that you're calling it on a homogenous nested array. As Paul notes, it won't give a correct answer for [[[1], 2], 3].
If this needs to be accounted for, you could write a recursive method which will iterate through each of the nested arrays and returning the minimum depth of the nesting.
protocol _Array {
func _nestingDepth(minimumDepth: Int?, currentDepth: Int) -> Int
}
extension Array : _Array {
func _nestingDepth(minimumDepth: Int?, currentDepth: Int) -> Int {
// for an empty array, the minimum depth is the current depth, as we know
// that _nestingDepth is called where currentDepth <= minimumDepth.
guard !isEmpty else { return currentDepth }
var minimumDepth = minimumDepth
for element in self {
// if current depth has exceeded minimum depth, then return the minimum.
// this allows for the short-circuiting of the function.
if let minimumDepth = minimumDepth, currentDepth >= minimumDepth {
return minimumDepth
}
// if element isn't an array, then return the current depth as the new minimum,
// given that currentDepth < minimumDepth.
guard let element = element as? _Array else { return currentDepth }
// get the new minimum depth from the next nesting,
// and incrementing the current depth.
minimumDepth = element._nestingDepth(minimumDepth: minimumDepth,
currentDepth: currentDepth + 1)
}
// the force unwrap is safe, as we know array is non-empty, therefore minimumDepth
// has been assigned at least once.
return minimumDepth!
}
var nestingDepth: Int {
return _nestingDepth(minimumDepth: nil, currentDepth: 1)
}
}
let a = [1, 2, 3]
print(a.nestingDepth) // 1
let b = [[1], [2], [3]]
print(b.nestingDepth) // 2
let c = [[[1], [2]], [[3]], [[5], [6]]]
print(c.nestingDepth) // 3
let d: [Any] = [ [[1], [2], [[3]] ], [[4]], [5] ]
print(d.nestingDepth) // 2 (the minimum depth is at element [5])

Great question that sent me off on a goose chase!
To be clear: I’m talking below about the approach of using the outermost array’s generic type parameter to compute the number of dimensions. As Tyrelidrel shows, you can recursively examine the runtime type of the first element — although this approach gives nonsensical answers for heterogenous arrays like [[[1], 2], 3].
Type-based dispatch can’t work
As you note, your code as written doesn’t work because numberOfDims is not defined for all types. But is there a workaround? Does this direction lead somewhere?
No, it’s a dead end. The reason is that extension methods are statically dispatched for non-class types, as the following snippet demonstrates:
extension CollectionType {
func identify() {
print("I am a collection of some kind")
}
func greetAndIdentify() {
print("Hello!")
identify()
}
}
extension Array {
func identify() {
print("I am an array")
}
}
[1,2,3].identify() // prints "I am an array"
[1,2,3].greetAndIdentify() // prints "Hello!" and "I am a collection of some kind"
Even if Swift allowed you to extend Any (and it doesn’t), Element.self.numberOfDims() would always call the Any implementation of numberOfDims() even if the runtime type of Element.self were an Array.
This crushing static dispatch limitation means that even this promising-looking approach fails (it compiles, but always returns 1):
extension CollectionType {
var numberOfDims: Int {
return self.dynamicType.numberOfDims
}
static var numberOfDims: Int {
return 1
}
}
extension CollectionType where Generator.Element: CollectionType {
static var numberOfDims: Int {
return 1 + Generator.Element.numberOfDims
}
}
[[1],[2],[3]].numberOfDims // return 1 ... boooo!
This same constraint also applies to function overloading.
Type inspection can’t work
If there’s a way to make it work, it would be something along these lines, which uses a conditional instead of type-based method dispatch to traverse the nested array types:
extension Array {
var numberOfDims: Int {
return self.dynamicType.numberOfDims
}
static var numberOfDims: Int {
if let nestedArrayType = Generator.Element.self as? Array.Type {
return 1 + nestedArrayType.numberOfDims
} else {
return 1
}
}
}
[[1,2],[2],[3]].numberOfDims
The code above compiles — quite confusingly — because Swift takes Array.Type to be a shortcut for Array<Element>.Type. That completely defeats the attempt to unwrap.
What’s the workaround? There isn’t one. This approach can’t work because we need to say “if Element is some kind of Array,” but as far as I know, there’s no way in Swift to say “array of anything,” or “just the Array type regardless of Element.”
Everywhere you mention the Array type, its generic type parameter must be materialized to a concrete type or a protocol at compile time.
Cheating can work
What about reflection, then? There is a way. Not a nice way, but there is a way. Swift’s Mirror is currently not powerful enough to tell us what the element type is, but there is another reflection method that is powerful enough: converting the type to a string.
private let arrayPat = try! NSRegularExpression(pattern: "Array<", options: [])
extension Array {
var numberOfDims: Int {
let typeName = "\(self.dynamicType)"
return arrayPat.numberOfMatchesInString(
typeName, options: [], range: NSMakeRange(0, typeName.characters.count))
}
}
Horrid, evil, brittle, probably not legal in all countries — but it works!

Unfortunately I was not able to do this with a Swift array but you can easily convert a swift array to an NSArray.
extension NSArray {
func numberOfDims() -> Int {
var count = 0
if let x = self.firstObject as? NSArray {
count += x.numberOfDims() + 1
} else {
return 1
}
return count
}
}

Related

How to extend String.Iterator in Swift

I have a String like LINNIIBDDDN, basically a series of tokens. I'd like to use multiple iterators, one for each token type. I'd like to have each iterator ignore the tokens that don't belong to it. That is, I want to call something like next_ish(), to advance the iterator to the next element of its particular token. So if the Niterator is at index 3, and I call next_ish(), I want it to go to index 10, the next N, not the I at index 4. I have some code that already works, but it's a lot of code, it makes the String into an array, and I have subclassed iterators, basically hand-written, with no help from Swift, although I'm sure the Swift iterators are more stable and thoroughly tested. I'd rather use their code than mine, where possible.
It seems like it should be easy just to extend String.Iterator and add next_ish(), but I'm at a loss. My first naive attempt was to extend String.Iterator. I get the error Constrained extension must be declared on the unspecialized generic type 'IndexingIterator' with constraints specified by a 'where' clause. I went looking to figure out what kind of where clause to use, and I haven't found anything.
There are a lot of answers here on SO, about extending arrays and generics, pulling all the elements of a certain type into an array of their own, even some answers about specialized for...in loops, but I can't find anything about extending iterators. I've read through Collections.swift and haven't found anything helpful. Is it possible to extend String.Iterator? That would make my life a lot easier. If not, is there some sort of built-in Swift mechanism for doing this sort of thing?
String.Iterator is (implicitly) defined as
typealias Iterator = IndexingIterator<String>
and the error message
Constrained extension must be declared on the unspecialized generic type 'IndexingIterator' with constraints specified by a 'where' clause
means that we must define extension methods as
extension IndexingIterator where Elements == String { }
Alternatively (with increasing generality):
extension IndexingIterator where Elements: StringProtocol { }
extension IndexingIterator where Elements.Element == Character { }
I haven't found a way to access the underlying collection (or position)
from within an extension method, the corresponding members are defined as
“internal”:
public struct IndexingIterator<Elements : Collection> {
internal let _elements: Elements
internal var _position: Elements.Index
// ...
}
What you can do is to pass the wanted element to your “next-ish” method,
either as the element itself, or as a predicate:
extension IndexingIterator where Elements.Element == Character {
mutating func next(_ wanted: Character) -> Character? {
while let c = next() {
if c == wanted { return c }
}
return nil
}
mutating func next(where predicate: ((Character) -> Bool)) -> Character? {
while let c = next() {
if predicate(c) { return c }
}
return nil
}
}
Example usage:
var it1 = "ABCDABCE".makeIterator()
print(it1.next("C") as Any) // Optional("C")
print(it1.next() as Any) // Optional("D")
print(it1.next("C") as Any) // Optional("C")
print(it1.next() as Any) // Optional("E")
print(it1.next("C") as Any) // nil
var it2 = "LINnIIBDDDN".makeIterator()
while let c = it2.next(where: { "Nn".contains($0) }) {
print(c, terminator: ", ")
}
print()
// N, n, N,
But actually I would consider String.Iterator being an IndexingIterator an implementation detail, and extend the IteratorProtocol instead:
extension IteratorProtocol where Element: Equatable {
mutating func next(_ wanted: Element) -> Element? {
while let e = next() {
if e == wanted { return e }
}
return nil
}
}
extension IteratorProtocol {
mutating func next(where predicate: ((Element) -> Bool)) -> Element? {
while let e = next() {
if predicate(e) { return e }
}
return nil
}
}
That makes it usable for arbitrary sequences. Example:
var it3 = [1, 1, 2, 3, 5, 8, 13, 21, 34].makeIterator()
while let e = it3.next(where: { $0 % 2 == 0} ) {
print(e, terminator: ", ")
}
print()
// 2, 8, 34,

Function accepting a generic Collection and returning an array of indices

I'm trying to write a function that accepts a generic Collection and a single element, then returns the index or indices of this element as an array. However, I'm getting an error at the return statement.
func findAll<T: Collection, U: Equatable>(_ items: T, _ find: U) -> [U] where T.Iterator.Element == U {
var found = [Int]()
for (index, item) in items.enumerated() {
if item == find {
found.append(index)
}
}
return found
}
Ken's answer is good, but Collection can have an Index other than Int. If you try to use the indexes you get back, you many not be able to subscript with them.
Instead of [Int], you want [Self.Index]. So instead of enumerated, you want the more general zip:
extension Collection where Self.Element: Equatable {
func indicesOfElements(equalTo element: Self.Element) -> [Self.Index] {
return zip(self.indices, self) // Zip together the index and element
.filter { $0.1 == element } // Find the ones that match
.map { $0.0 } // Return the elements
}
}
[1,2,3,4,1].indicesOfElements(equalTo: 1) // => [0,4]
That said, a simpler approach would be:
extension Collection where Self.Element: Equatable {
func indicesOfElements(equalTo element: Self.Element) -> [Self.Index] {
return indices.filter { self[$0] == element }
}
}
To see the problem w/ subscripting, consider this:
let s = "abcabc"
let i = s.indicesOfElements(equalTo: "a").first!
s[i] // "a"
let j = findAll(s, "a").first!
s[j] // error: 'subscript' is unavailable: cannot subscript String with an Int, see the documentation comment for discussion
While a protocol extension is the preferred way to do this in Swift, this is directly convertible to the following generic function syntax:
func indicesOfElements<C: Collection>(in collection: C, equalTo element: C.Element) -> [C.Index]
where C.Element: Equatable {
return collection.indices.filter { collection[$0] == element }
}
The following style is also equivalent, and has a slightly shallower learning curve (no need for filter.
func simplerIndicesOfElements<C: Collection>(in collection: C, equalTo element: C.Element) -> [C.Index]
where C.Element: Equatable {
var results: [C.Index] = []
for index in collection.indices {
if collection[index] == element {
results.append(index)
}
}
return results
}
I believe even fairly new Swift developers should learn to read simple filter and map expressions (though these should aways be kept simple, even by experts!) But there is absolutely nothing wrong with learning simple for iteration first.
If you're just getting started, note the naming style here as well. Your initial example included two unnamed parameters. In many (most) cases this is poor Swift. In Swift we generally try to name our parameters such that they read fairly naturally in English. In findAll(xs, x) it's unclear what the parameters are or what the return value will be in. In indicesOfElements(in: xs, equalTo: x), all the information is available at the call site.
In Swift 3, this takes a lot more syntax than you probably expect:
func indicesOfElements<C: Collection>(in collection: C, equalTo element: C.Iterator.Element) -> [C.Index]
where C.Iterator.Element: Equatable, C.Indices.Iterator.Element == C.Index {
// ... Same body ...
}
In Swift 3, associated types can't have additional constraints put on them. This seems a small thing, but it's huge. It means that there's no way to say Collection.Indices actually contains Collection.Index. And there's no way to create a Collection.Element (the type returned by subscripting the collection) that is promised to be the same as Collection.Iterator.Element (the type returned by iterating over the collection). This leads to a lot of C.Iterator... and where clauses that seem obvious like C.Indices.Iterator.Element == C.Index.
If you're near the start of your Swift journey, I'd probably skip over the generics entirely, and write this in terms of [Int]. A very common mistake by Swift programmers (new and "old") is to jump to generic programming before they have any need of it. But if you're at the stage where you're tackling generics, this is how you often have to write them in Swift 3. (Swift 4 is a dramatic improvement for generic programming.)
Since you would like to return the indices of the found elements, you should return an array of Ints instead of [U]. Here's the updated code:
func findAll<T: Collection, U: Equatable>(_ items: T, _ find: U)
-> [Int] where T.Iterator.Element == U {
var found = [Int]()
for (index, item) in items.enumerated() {
if item == find {
found.append(index)
}
}
return found
}
And here's a test case:
let numbers = [1,0,1,0,0,1,1]
let indicesOfOnes = findAll(numbers, 1)
print(indicesOfOnes)
Which will print:
[0, 2, 5, 6]

Calculate the number of dimensions of a multi-dimensional array in Swift

Suppose I have some function that I want to populate my data structure using a multi-dimensional array (e.g. a Tensor class):
class Tensor {
init<A>(array:A) { /* ... */ }
}
while I could add in a shape parameter, I would prefer to automatically calculate the dimensions from the array itself. If you know apriori the dimensions, it's trivial to read it off:
let d1 = array.count
let d2 = array[0].count
However, it's less clear how to do it for an N-dimensional array. I was thinking there might be a way to do it by extending the Array class:
extension Int {
func numberOfDims() -> Int {
return 0
}
}
extension Array {
func numberOfDims() -> Int {
return 1+Element.self.numberOfDims()
}
}
Unfortunately, this won't (rightfully so) compile, as numberOfDims isn't defined for most types. However, I'm don't see any way of constraining Element, as Arrays-of-Arrays make things complicated.
I was hoping someone else might have some insight into how to solve this problem (or explain why this is impossible).
If you're looking to get the depth of a nested array (Swift's standard library doesn't technically provide you with multi-dimensional arrays, only jagged arrays) – then, as shown in this Q&A, you can use a 'dummy protocol' and typecasting.
protocol _Array {
var nestingDepth: Int { get }
}
extension Array : _Array {
var nestingDepth: Int {
return 1 + ((first as? _Array)?.nestingDepth ?? 0)
}
}
let a = [1, 2, 3]
print(a.nestingDepth) // 1
let b = [[1], [2, 3], [4]]
print(b.nestingDepth) // 2
let c = [[[1], [2]], [[3]], [[4], [5]]]
print(c.nestingDepth) // 3
(I believe this approach would've still worked when you had originally posted the question)
In Swift 3, this can also be achieved without a dummy protocol, but instead by casting to [Any]. However, as noted in the linked Q&A, this is inefficient as it requires traversing the entire array in order to box each element in an existential container.
Also note that this implementation assumes that you're calling it on a homogenous nested array. As Paul notes, it won't give a correct answer for [[[1], 2], 3].
If this needs to be accounted for, you could write a recursive method which will iterate through each of the nested arrays and returning the minimum depth of the nesting.
protocol _Array {
func _nestingDepth(minimumDepth: Int?, currentDepth: Int) -> Int
}
extension Array : _Array {
func _nestingDepth(minimumDepth: Int?, currentDepth: Int) -> Int {
// for an empty array, the minimum depth is the current depth, as we know
// that _nestingDepth is called where currentDepth <= minimumDepth.
guard !isEmpty else { return currentDepth }
var minimumDepth = minimumDepth
for element in self {
// if current depth has exceeded minimum depth, then return the minimum.
// this allows for the short-circuiting of the function.
if let minimumDepth = minimumDepth, currentDepth >= minimumDepth {
return minimumDepth
}
// if element isn't an array, then return the current depth as the new minimum,
// given that currentDepth < minimumDepth.
guard let element = element as? _Array else { return currentDepth }
// get the new minimum depth from the next nesting,
// and incrementing the current depth.
minimumDepth = element._nestingDepth(minimumDepth: minimumDepth,
currentDepth: currentDepth + 1)
}
// the force unwrap is safe, as we know array is non-empty, therefore minimumDepth
// has been assigned at least once.
return minimumDepth!
}
var nestingDepth: Int {
return _nestingDepth(minimumDepth: nil, currentDepth: 1)
}
}
let a = [1, 2, 3]
print(a.nestingDepth) // 1
let b = [[1], [2], [3]]
print(b.nestingDepth) // 2
let c = [[[1], [2]], [[3]], [[5], [6]]]
print(c.nestingDepth) // 3
let d: [Any] = [ [[1], [2], [[3]] ], [[4]], [5] ]
print(d.nestingDepth) // 2 (the minimum depth is at element [5])
Great question that sent me off on a goose chase!
To be clear: I’m talking below about the approach of using the outermost array’s generic type parameter to compute the number of dimensions. As Tyrelidrel shows, you can recursively examine the runtime type of the first element — although this approach gives nonsensical answers for heterogenous arrays like [[[1], 2], 3].
Type-based dispatch can’t work
As you note, your code as written doesn’t work because numberOfDims is not defined for all types. But is there a workaround? Does this direction lead somewhere?
No, it’s a dead end. The reason is that extension methods are statically dispatched for non-class types, as the following snippet demonstrates:
extension CollectionType {
func identify() {
print("I am a collection of some kind")
}
func greetAndIdentify() {
print("Hello!")
identify()
}
}
extension Array {
func identify() {
print("I am an array")
}
}
[1,2,3].identify() // prints "I am an array"
[1,2,3].greetAndIdentify() // prints "Hello!" and "I am a collection of some kind"
Even if Swift allowed you to extend Any (and it doesn’t), Element.self.numberOfDims() would always call the Any implementation of numberOfDims() even if the runtime type of Element.self were an Array.
This crushing static dispatch limitation means that even this promising-looking approach fails (it compiles, but always returns 1):
extension CollectionType {
var numberOfDims: Int {
return self.dynamicType.numberOfDims
}
static var numberOfDims: Int {
return 1
}
}
extension CollectionType where Generator.Element: CollectionType {
static var numberOfDims: Int {
return 1 + Generator.Element.numberOfDims
}
}
[[1],[2],[3]].numberOfDims // return 1 ... boooo!
This same constraint also applies to function overloading.
Type inspection can’t work
If there’s a way to make it work, it would be something along these lines, which uses a conditional instead of type-based method dispatch to traverse the nested array types:
extension Array {
var numberOfDims: Int {
return self.dynamicType.numberOfDims
}
static var numberOfDims: Int {
if let nestedArrayType = Generator.Element.self as? Array.Type {
return 1 + nestedArrayType.numberOfDims
} else {
return 1
}
}
}
[[1,2],[2],[3]].numberOfDims
The code above compiles — quite confusingly — because Swift takes Array.Type to be a shortcut for Array<Element>.Type. That completely defeats the attempt to unwrap.
What’s the workaround? There isn’t one. This approach can’t work because we need to say “if Element is some kind of Array,” but as far as I know, there’s no way in Swift to say “array of anything,” or “just the Array type regardless of Element.”
Everywhere you mention the Array type, its generic type parameter must be materialized to a concrete type or a protocol at compile time.
Cheating can work
What about reflection, then? There is a way. Not a nice way, but there is a way. Swift’s Mirror is currently not powerful enough to tell us what the element type is, but there is another reflection method that is powerful enough: converting the type to a string.
private let arrayPat = try! NSRegularExpression(pattern: "Array<", options: [])
extension Array {
var numberOfDims: Int {
let typeName = "\(self.dynamicType)"
return arrayPat.numberOfMatchesInString(
typeName, options: [], range: NSMakeRange(0, typeName.characters.count))
}
}
Horrid, evil, brittle, probably not legal in all countries — but it works!
Unfortunately I was not able to do this with a Swift array but you can easily convert a swift array to an NSArray.
extension NSArray {
func numberOfDims() -> Int {
var count = 0
if let x = self.firstObject as? NSArray {
count += x.numberOfDims() + 1
} else {
return 1
}
return count
}
}

Java-like Iterator in Swift

How to iterate array without using position (index) i and for/for in loop?
var a = [1, 2, 3]
for var i = 0; i < a.count; i++ {
//
}
for item in a {
//
}
A SequenceType (which CollectionType, and thus all Swift collections including array, conform to) is pretty simple. It requires you provide a generate() function that returns a type conforming to GeneratorType.
GeneratorType in turn only needs to provide one method: a next() that returns each element until the elements are exhausted. It returns an optional, returning nil after the last element is returned. This makes them pretty similar to Java iterators, only with next and hasNext combined into one via use of optionals.
Swift’s for…in is really syntactic sugar for a combination of getting a generator and then repeatedly calling next on it:
let a = [1, 2, 3]
for i in a { print(i) }
// is equivalent to:
var g = a.generate()
// the generator, being stateful, must be declared with var
while let i = g.next() { print(i) }
If using generators like this, take note of the comment above the definition of GeneratorType in the std lib doc:
Encapsulates iteration state and interface for iteration over a
sequence.
Note: While it is safe to copy a generator, advancing one
copy may invalidate the others.
Since writing a generator for a collection often involves a lot of boiler plate, there is a helper type, IndexingGenerator, that can be used. This implements a generator that starts at startIndex, and returns the value at that index and increments the index each time. A generate() that returns an IndexingGenerator is provided as the default implementation for CollectionType, which means if this is good enough for your purposes, you don’t need to implement generate when implementing a collection:
struct Bitfield: CollectionType {
let data: UInt
var startIndex: UInt { return 0 }
var endIndex: UInt { return UInt(sizeofValue(data)*8) }
subscript(idx: UInt) -> Bit {
return (data >> idx) & 1 == 0
? Bit.Zero : Bit.One
}
// no need to implement generate()
}
This default was added in Swift 2.0. Prior to that, you had to provide a minimal generator that just returned an IndexingGenerator(self).
You can do it using IndexingGenerator:
var a = [1, 2, 3]
var generator = a.generate()
while let item = generator.next() {
//
}
P. S. I created and answered my own question because I did not find anything when tried to figure out how to use Java-like iterators in Swift.
It could be done with the help of IteratorProtocol.
let a = [1, 2, 3]
var aIterator = a.makeIterator()
while let aItem = aIterator.next() {
// do something with array item
}
More on IteratorProtocol in Apple's documentation here
if you use Java 8 you can use streams.
As an example:
List<User> olderUsers = users.stream().filter(u -> u.age > 30).collect(Collectors.toList());

Any way to iterate a tuple in swift?

I am curious how to do a for loop with a tuple in swift.
I know that to access each member you can use dot notation using the index number
var tupleList = ("A",2.9,3,8,5,6,7,8,9)
for each in tupleList {
println(each)
}
//Error: Type does not conform to protocol sequence
Yes, you can!
func iterate<C,R>(t:C, block:(String,Any)->R) {
let mirror = reflect(t)
for i in 0..<mirror.count {
block(mirror[i].0, mirror[i].1.value)
}
}
And voila!
let tuple = ((false, true), 42, 42.195, "42.195km")
iterate(tuple) { println("\($0) => \($1)") }
iterate(tuple.0){ println("\($0) => \($1)")}
iterate(tuple.0.0) { println("\($0) => \($1)")} // no-op
Note the last one is not a tuple so nothing happens (though it is a 1-tuple or "Single" which content can be accessed .0, reflect(it).count is 0).
What's interesting is that iterate() can iterate even other types of collection.
iterate([0,1]) { println("\($0) => \($1)") }
iterate(["zero":0,"one":1]) { println("\($0) => \($1)") }
And that collection includes class and struct!
struct Point { var x = 0.0, y = 0.0 }
class Rect { var tl = Point(), br = Point() }
iterate(Point()) { println("\($0) => \($1)") }
iterate(Rect()) { println("\($0) => \($1)") }
Caveat: the value passed as the 2nd argument of the block is type Any. You have to cast it back to the values with original type.
You can using reflection Swift 5
Try this in a Playground:
let tuple = (1, 2, "3")
let tupleMirror = Mirror(reflecting: tuple)
let tupleElements = tupleMirror.children.map({ $0.value })
tupleElements
Output:
Swift does not currently support iterating over tuples.
The biggest reasons are:
There is no way at runtime to determine the number of elements in a tuple
There is no way to access an element at a specific index except for the compile time accessors like tupleList.0. You would really want a subscript tupleList[0] but that is not provided to us
Frankly, I can't see a reason that you would use a tuple instead of an Array if you want to iterate over it.
It doesn't make sense to iterate over a tuple because:
Tuples always have a fixed length and each element has a fixed type
You can name each tuple member with a name you can use to access it later
Arrays are well made to iterate over:
Arbitrary length
Can store multiple types using a common superclass or AnyObject
Can be declared as a literal in a similar fashion to tuples: var list = ["A",2.9,3,8,5,6,7,8,9]
#dankogai's excellent solution, updated for Swift 3.0:
func iterate<Tuple>(_ tuple:Tuple, body:(_ label:String?,_ value:Any)->Void) {
for child in Mirror(reflecting: tuple).children {
body(child.label, child.value)
}
}
Usage remains identical to #dankogai's examples (beyond Swift 2's println()→print() rename).
Note that the label is now of type String? when it was formerly String, to match the type change from Swift 1's MirrorType.subscript(…).0 to Swift 3's Mirror.Child.label.  However, for labelless tuples the label arg comes back as ".0", ".1", ".2", etc.— it's only nil for some other types.
Also, I took the liberty of renaming types & args to better match Swift 3's solidified naming standards, and changing the closure return type to Void.
Sidenote: I noticed somebody downvoted me here— I can't imagine why, other than the (fair) argument that building app functionality around reflection in Swift is hacking the type system, and is likely to lead to crappy code throughout (Swift's tuples shouldn't be considered an abstract data type, but rather a small collection of variables, akin to method args).  As a counter-argument, I originally ended up porting this to Swift 3 in project because I needed it— for better descriptions and debugDescriptions.  Because sane debug output will saves you hours and hours of frustration. ;-)  Additionally, this could be really useful for unit tests… because tests are ultimately most interested in “did the result of this operation match what we expect?”
Details
Xcode 11.2.1 (11B500), Swift 5.1
Base 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 forEach(closure: (Mirror.Child) -> Void) { array.forEach { closure($0) } }
func getOnlyValues<T: Any>() -> [T] { array.compactMap { $0.value as? T } }
func getAllValues() -> [Any] { array.compactMap { $0.value } }
}
Usage on base solution
let num: Int? = 3
let str: String? = nil
let x = (1, "stew", str, 5.4, 2, num)
let tuple = Tuple(x)
tuple.forEach { print("\($0)") }
print("\(tuple.getAllValues())") // [1, "stew", nil, 5.4, 2, Optional(3)]
print("\(tuple.getOnlyValues() as [Int])") // [1, 2, 3]
More sugar
func valuesFrom<V>(tuple: V) -> [Any] { return Tuple(tuple).getAllValues() }
func onlyValuesFrom<T,V>(tuple: V) -> [T] { return Tuple(tuple).getOnlyValues() as [T] }
print(valuesFrom(tuple: x)) // [1, "stew", nil, 5.4, 2, Optional(3)]
print(onlyValuesFrom(tuple: x) as [Int]) // [1, 2, 3]
No, you can't. The reason is that tuple items are not all required to have the same type, so you would not be able to know what type each should have.