¿Cómo hago indexOfObject o un proper containsObject?

Con una matriz: ¿Cómo hago indexOfObject o un proper containsObject ?

Quiero decir que sé que podría unir el Array a NSArray y hacerlo allí ^^
Pero debe haber una forma "nativa" de hacer esto

PS para containsObject Supongo que también podría filtrar la matriz, pero para indexOf ?

Puede usar el find integrado y, por lo tanto, evitar el puente a Objective-C, pero solo si su tipo de elemento es Equatable . (Si no es Equivocado, puede hacerlo con una function de comparación y una extensión).

Ejemplo:

 func == (lhs:Piece,rhs:Piece) -> Bool { return lhs.val == rhs.val } class Piece:Equatable,Printable { var val : Int var description : String { return String(val) } init (_ v:Int) { val = v } } 

Ahora puedes llamar a find(arr,p) donde arr es un Array<Piece> p es un Piece .

Una vez que tenga esto, puede desarrollar utilidades basadas en él. Por ejemplo, aquí hay una function global para eliminar un object de una matriz sin unir a Objective-C:

 func removeObject<T:Equatable>(inout arr:Array<T>, object:T) -> T? { if let found = find(arr,object) { return arr.removeAtIndex(found) } return nil } 

Y pruébelo así:

 var arr = [Piece(1), Piece(2), Piece(3)] removeObject(&arr,Piece(2)) println(arr) 

También puede hacer esto para las subclasss NSObject. Ejemplo:

 func == (v1:UIView, v2:UIView) -> Bool { return v1.isEqual(v2) } extension UIView : Equatable {} 

Ahora puede llamar a find en una matriz de UIView. Es una especie de dolor en el trasero, sin embargo, tener que hacer esto para cada class en la que quieras poder find en una matriz de esa class. He presentado una request de mejora con Apple solicitando que todas las subclasss de NSObject se consideren Equivables y que == debería recurrir a isEqual: automáticamente .

EDITAR Comenzando en Semilla 3, esto es automático para UIView y otras classs de NSObject. Entonces, ahora solo funciona para ellos.

EDIT 2 Comenzando en Swift 2.0, indexOf existirá como un método:

 let s = ["Manny", "Moe", "Jack"] let ix = s.indexOf("Moe") // 1 

Alternativamente, toma una function que devuelve Bool:

 let ix2 = s.indexOf {$0.hasPrefix("J")} // 2 

Nuevamente, esto funciona solo en collections de Equatable, ya que obviamente no se puede ubicar una aguja en un pajar a less que tenga una forma de identificar una aguja cuando se encuentre con ella.

EDIT 3 Swift 2.0 también presenta extensiones de protocolo. ¡Esto significa que puedo reescribir mi function global removeObject como método!

Por ejemplo:

 extension RangeReplaceableCollectionType where Generator.Element : Equatable { mutating func removeObject(object:Self.Generator.Element) { if let found = self.indexOf(object) { self.removeAtIndex(found) } } } 

Como Array adopta RangeReplaceableCollectionType, ahora puedo escribir un código como este:

 var arr = [Piece(1), Piece(2), Piece(3)] arr.removeObject(Piece(2)) 

¡Oh dia feliz!

En realidad, se puede hacer en Swift. Para get el índice use find(YourArray, ObjectToFind)

Como me dijeron, esto aún no está disponible / tengo que conectarlo a NSArray

No me gusta esto y se siente sucio, así que fui y lo hice en una extensión. De esa forma, oculta el uso de NSArray y permite que Apple lo proporcione más tarde.

 import Foundation extension Array { func contains(object:AnyObject!) -> Bool { if(self.isEmpty) { return false } let array: NSArray = self.bridgeToObjectiveC(); return array.containsObject(object) } func indexOf(object:AnyObject!) -> Int? { var index = NSNotFound if(!self.isEmpty) { let array: NSArray = self.bridgeToObjectiveC(); index = array.indexOfObject(object) } if(index == NSNotFound) { return Optional.None; } return index } //#pragma mark KVC func getKeyPath(keyPath: String!) -> AnyObject! { return self.bridgeToObjectiveC().valueForKeyPath(keyPath); } } 

https://gist.github.com/Daij-Djan/9d1c4b1233b4017f3b67

Apple proporciona un ejemplo de esto exactamente en el libro de The Swift Programming Language . Específicamente, vea la sección sobre Restricciones de tipo en acción ( p621 en el iBook ).

 func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? { for (index, value) in enumerate(array) { if value == valueToFind { return index } } return nil } 

Todo depende de su tipo de implementación Equatable .

El lenguaje de progtwigción Swift lo cubre y explica cómo implementar ese protocolo:

"La biblioteca estándar Swift define un protocolo llamado Equatable, que requiere cualquier tipo de conformidad para implementar el operador igual (==) y el operador no igual (! =) Para comparar dos valores de ese tipo. "

NSHipster tiene un par de publicaciones relevantes sobre este tema:

Implementaciones rápidas del protocolo Swift Protocolos de comparación rápida

También encontré esta respuesta muy útil en la implementación de Equatable:

¿Cómo implemento el protocolo comparable de Swift?

Aunque menciona Comparable, Equatable es un subset y la explicación es buena.

Extractos anteriores de: Apple Inc. "The Swift Programming Language". IBooks. https://itun.es/gb/jEUH0.l

Otra opción es usar el filter:

 haystack.filter({$0 == needle}).count > 0 

Esto verifica si el array haystack contiene una aguja de object.

No puedes Es por eso que NSArray todavía está allí. Sin embargo, la documentation de Apple dice lo siguiente sobre String y NSString :

El tipo de cadena de Swift se conecta a la perfección con la class NSString de Foundation. Si está trabajando con el framework Foundation en Cocoa o Cocoa Touch, toda la API de NSString está disponible para invocar cualquier valor de cadena que cree, además de las características de cadena descritas en este capítulo. También puede usar un valor de cadena con cualquier API que requiera una instancia de NSString.

Siguiendo ese enfoque, la API NSArray debería estar disponible en Array , pero no se debe a que la Array nativa Swift sea primitiva (probablemente sea una estructura o similar), por lo que debe "convertirla" a una NSArray .

Parece que no todos los puentes gratuitos del espacio NS / CF están en su lugar. Sin embargo, si declara su matriz como NSArray, funciona bien:

 let fruits: NSArray = [ "apple", "orange", "tomato (really?)" ] let index = fruits.indexOfObject("orange") println("Index of Orange: \(index)") 

Si los elementos de la matriz son objects y desea encontrar un object idéntico en esa matriz, puede usar esta function:

 func findObject<C: CollectionType where C.Generator.Element: AnyObject>(domain: C, value: C.Generator.Element) -> Int? { for (index, element) in enumerate(domain) { if element === value { return index } } return nil }