我如何做indexOfObject或一个适当的containsObject

用数组:我怎么做indexOfObject或一个正确的containsObject

我的意思是我知道我可以将数组连接到NSArray ,并在那里做^^
但是这样做肯定有一种“本土的”方式

PS为containsObject我想我也可以过滤数组,但对于indexOf

您可以使用内置的find ,从而避免桥接到Objective-C – 但只有当您的元素types是Equatable时 。 (如果它不是可等值的,可以通过比较函数和扩展来实现。)

例:

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

现在你可以调用find(arr,p) ,其中arr是一个Array<Piece>p是一个Piece

一旦你有这个,你可以开发基于它的实用程序。 例如,下面是一个全局函数,用于从数组中删除一个对象而不桥接到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 } 

并testing它是这样的:

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

你也可以为NSObject子类做这个。 例:

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

现在你可以调用一个UIView的数组了。 但是,对于每一个你希望能够在这个类的Array上使用find类都必须这样做。 我已经提交了一个增强请求与苹果请求所有的NSObject子类被认为是可衡量的, ==应该回落isEqual: 自动

编辑从种子3开始,这 UIView和其他NSObject类自动。 所以现在find适合他们的工作。

编辑2从Swift 2.0开始, indexOf将作为一种方法存在:

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

或者,它需要一个返回Bool的函数:

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

再次,这只适用于Equatable集合,因为显然你不能find一个大海捞针,除非你有一个方法来确定一个针,当你来到它。

编辑3 Swift 2.0还引入了协议扩展。 这意味着我可以重写我的全局函数removeObject作为一种方法!

例如:

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

由于Array采用RangeReplaceableCollectionType,现在我可以编写这样的代码:

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

哦,快乐的一天!

它实际上可以在Swift中完成。 要获得索引使用find(YourArray, ObjectToFind)

据我所知,这还没有/我必须把它连接到NSArray

我不喜欢这个,感觉很脏,所以我去了,做了一个扩展。 这样它隐藏了NSArray的使用,并允许苹果以后提供

 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在Swift编程语言手册中提供了一个正确的例子。 具体来说,请参阅“types约束实际操作”一节( iBook中的p621 )。

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

一切都取决于你的types实现Equatable 。

Swift编程语言涵盖了这一点,并解释了如何实现该协议:

“Swift标准库定义了一个名为Equatable的协议,它要求任何符合types实现等于运算符(==)和不等于运算符(!=)来比较任何两个这种types的值。 ”

NSHipster在这方面有几个相关的post:

Swift默认协议实现 Swift比较协议

我也发现这个答案在实现Equatable时非常有用:

我如何实现Swift的Comparable协议?

虽然它提到了Comparable,但Equatable是一个子集,解释是好的。

以上摘自:苹果公司“Swift编程语言”,iBooks。 https://itun.es/gb/jEUH0.l

另一个select是使用filter:

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

这检查arrays干草堆是否包含对象针。

你不能。 这就是为什么NSArray仍然在那里。 但是,Apple文档中关于StringNSString内容如下所示:

Swift的Stringtypes无缝桥接到Foundation的NSString类。 如果您正在使用Cocoa或Cocoa Touch中的Foundation框架,则除了本章中介绍的stringfunction之外,还可以使用整个NSString API调用您创build的任何string值。 您也可以使用任何需要NSString实例的API来使用String值。

遵循这种方法, NSArray API 应该Array上可用,但这不是因为本地Swift Array是一个原语(很可能是一个结构或类似的),所以你必须“转换”成一个NSArray

似乎并非所有NS / CF空间的免费桥接都已到位。 但是,如果你将你的数组声明为一个NSArray,它可以正常工作:

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

如果你的数组元素是对象,并且你想在这个数组中find一个相同的对象,你可以使用这个函数:

 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 }