2016-05-19 8 views
6

Lassen Sie uns sagen, dass ich dieses Array haben:Wie findet man den Index eines Artikels in einem multidimensionalen Array schnell?

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

Jetzt möchte ich etwas wie folgt aus:

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

so, dass ich es so nennen kann:

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

Natürlich, ich kann verwenden:

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

Aber das ist nicht mal knapp!

Ich möchte einen Weg, dies zu tun, die swifty ist. Ich denke, vielleicht kann ich reduce oder map verwenden?

+0

Es

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 } 

Ebenso ist eine Erweiterung für eine verschachtelte Array von Equatable Elemente machen Für diesen Fall ist es nicht sinnvoll, 'map/filter/reduce' zu ​​verwenden, da Sie eine Liste von Objekten nicht in eine Liste umwandeln müssen von einer anderen Sache. Sie müssen nur eine Art von Gleichheitsüberprüfung zwischen den Werten durchführen, indem Sie 'enumerate()' verwenden, wenn Sie denken, dass tiefgestellt und '.count' hässlich aussieht. – ozgur

Antwort

8

Sie können Ihren Code leicht mit enumerate() und indexOf() vereinfachen. Auch die Funktion sollte ein optionales Tupel zurückgeben, da das Element möglicherweise nicht in der "Matrix" vorhanden ist. Schließlich können Sie es Generika machen:

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

Danke! Ich wusste eigentlich nicht, dass "aufzählen" bis jetzt nützlich ist! – Sweeper

Verwandte Themen