我如何做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); } }
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文档中关于String
和NSString
内容如下所示:
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 }