2016-05-19 11 views
6

Diciamo che ho questo array:Come trovare rapidamente l'indice di un elemento in una matrice multidimensionale?

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

Ora voglio qualcosa di simile:

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

modo che io possa chiamare in questo modo:

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

Naturalmente, ho può usare:

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

Ma non è nemmeno vicino a swifty!

Voglio un modo per fare questo che è swifty. Penso che forse posso usare reduce o map?

+0

E' non ha senso usare 'map/filter/reduce' per questo caso perché non è necessario trasformare una lista di qualcosa in una lista di un'altra cosa Devi solo fare una sorta di controllo di uguaglianza tra i valori usando 'enumerate()' se pensi che subscript e '.count' siano brutti. – ozgur

risposta

8

È possibile semplificare leggermente il codice con enumerate() e indexOf(). Anche la funzione dovrebbe restituire una tupla opzionale perché l'elemento potrebbe non essere presente nella "matrice". Infine, si può rendere generico:

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 
} 

E 'possibile fare una proroga per un nidificato Array di Equatable elementi:

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 
    } 
} 
+0

Grazie! In realtà non sapevo che 'enumerate' è _questo_ utile fino ad ora! – Sweeper