对于一个数组:如何实现indexOfObject
或containsObject
方法?
我的意思是,我知道可以将该数组桥接到NSArray
中并在那里执行这些方法^^
但肯定有一种“本地”的方法来实现此操作。
附:对于containsObject
方法,我想我也可以过滤数组,但是对于indexOf方法呢?
对于一个数组:如何实现indexOfObject
或containsObject
方法?
我的意思是,我知道可以将该数组桥接到NSArray
中并在那里执行这些方法^^
但肯定有一种“本地”的方法来实现此操作。
附:对于containsObject
方法,我想我也可以过滤数组,但是对于indexOf方法呢?
find
函数,从而避免桥接到Objective-C——但前提是您的元素类型是可比较的。(如果它不是可比较的,您可以通过比较函数和扩展来使其可比较。)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
。func removeObject<T:Equatable>(inout arr:Array<T>, object:T) -> T? {
if let found = find(arr,object) {
return arr.removeAtIndex(found)
}
return nil
}
然后像这样测试它:
var arr = [Piece(1), Piece(2), Piece(3)]
removeObject(&arr,Piece(2))
println(arr)
func == (v1:UIView, v2:UIView) -> Bool {
return v1.isEqual(v2)
}
extension UIView : Equatable {}
find
。但是,如果您想在每个要使用该类的数组上使用find
,这可能有点麻烦。我已向Apple提交了增强请求,请求将所有NSObject子类视为可比较,并且==
应自动回退到isEqual:
。find
现在适用于它们。indexOf
将作为一种方法存在:let s = ["Manny", "Moe", "Jack"]
let ix = s.indexOf("Moe") // 1
或者,它可以接受一个返回布尔值的函数:
let ix2 = s.indexOf {$0.hasPrefix("J")} // 2
需要注意的是,这个方法只适用于实现了Equatable协议的集合类型。显然,如果没有办法在找到一个元素时对其进行识别,那么就无法在集合中查找该元素。
编辑 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)
}
}
}
由于数组采用了RangeReplaceableCollectionType,因此现在我可以编写以下代码:
var arr = [Piece(1), Piece(2), Piece(3)]
arr.removeObject(Piece(2))
哦,愉快的一天!
indexOf()
变成了index(of:)
。 - ThomasW实际上,这可以用Swift完成。要获取索引,请使用find(YourArray, ObjectToFind)
。
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);
}
}
另一个选择是使用过滤器:
haystack.filter({$0 == needle}).count > 0
该函数检查数组 haystack 中是否包含元素 needle。
func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
for (index, value) in enumerate(array) {
if value == valueToFind {
return index
}
}
return nil
}
NSArray
仍然存在的原因。但是,关于 String
和 NSString
,苹果文档如下所述:Array
应该可以使用 NSArray
API,但事实并非如此,因为本地 Swift Array
是一个基元(很可能是结构体或类似结构),所以您必须将其“转换”为 NSArray
。看起来并不是所有的NS/CF空间的免费桥接都已经到位。但是,如果您将数组声明为NSArray,则可以正常工作:
let fruits: NSArray = [ "apple", "orange", "tomato (really?)" ]
let index = fruits.indexOfObject("orange")
println("Index of Orange: \(index)")
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
}