How to quickly find the index of an element in a multidimensional array?

Let's say I have this array:

let a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

Now I want something like this:

 public func indicesOf(x: Int, array: [[Int]]) -> (Int, Int) { ... } 

so I can call it that:

 indicesOf(7, array: a) // returns (2, 0) 

Of course I can use:

 for i in 0..<array.count { for j in 0..<array[i].count { if array[i][j] == x { return (i, j) } } } 

But it’s not even close to fast!

I want a way to do it fast. I think maybe I can use reduce or map ?

+8
source share
2 answers

You can simplify your code a bit with enumerate() and indexOf() . Also, the function must return an optional tuple, because the element may not be present in the "matrix". Finally, you can make it general:

 func indicesOf<T: Equatable>(x: T, array: [[T]]) -> (Int, Int)? { for (i, row) in array.enumerate() { if let j = row.indexOf(x) { return (i, j) } } return nil } 

You can also make it an extension for a nested Array of Equatable elements:

 extension Array where Element : CollectionType, Element.Generator.Element : Equatable, Element.Index == Int { func indicesOf(x: Element.Generator.Element) -> (Int, Int)? { for (i, row) in self.enumerate() { if let j = row.indexOf(x) { return (i, j) } } return nil } } if let (i, j) = a.indicesOf(7) { print(i, j) } 

Swift 3:

 extension Array where Element : Collection, Element.Iterator.Element : Equatable, Element.Index == Int { func indices(of x: Element.Iterator.Element) -> (Int, Int)? { for (i, row) in self.enumerated() { if let j = row.index(of: x) { return (i, j) } } return nil } } 
+12
source

The version that takes the closure is similar to the index (where :) , so there it can be used in an array of any elements, not just Equatable

 extension Array where Element : Collection, Element.Index == Int { func indices(where predicate: (Element.Iterator.Element) -> Bool) -> (Int, Int)? { for (i, row) in self.enumerated() { if let j = row.index(where: predicate) { return (i, j) } } return nil } } 

Use like this:

 let testArray = [[1,2,3], [4,5,6], [7,8]] let testNumber = 6 print(testArray.indices(of: testNumber)) print(testArray.indices{$0 == testNumber}) Optional((1, 2)) Optional((1, 2)) 

It can also be used with IndexPath :

 extension Array where Element : Collection, Element.Index == Int { func indexPath(where predicate: (Element.Iterator.Element) -> Bool) -> IndexPath? { for (i, row) in self.enumerated() { if let j = row.index(where: predicate) { return IndexPath(indexes: [i, j]) } } return nil } } 
+5
source

All Articles