我该如何做indexOfObject或一个合适的containsObject

时间:2014-06-03 08:41:45

标签: ios arrays swift

使用数组:如何indexOfObject或正确containsObject

我的意思是我知道我可以将数组桥接到NSArray并在那里做^^
但必须有一个“本地人”。这样做的方式

P.S。对于containsObject,我想我也可以过滤数组但是 indexOf

8 个答案:

答案 0 :(得分:44)

您可以使用内置的find,从而避免桥接到Objective-C - 但前提是您的元素类型为Equatable。 (如果它不是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),其中arrArray<Piece>pPiece

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

并按照以下方式进行测试:

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数组上调用find。但是,对于你希望能够在该类的数组上使用find的每个类都必须这样做,这对于屁股来说是一种痛苦。我已经向Apple提交了一个增强请求,要求将所有NSObject子类视为Equatable,==应该自动返回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的集合,因为很明显你不能在大海捞针中找到一根针,除非你有一种识别针的方法。

编辑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))

哦,快乐的一天!

答案 1 :(得分:9)

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

获取索引

答案 2 :(得分:4)

据我所知,这还不可用/我必须将它连接到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

答案 3 :(得分:2)

Apple在The Swift Programming Language一书中提供了一个这样的例子。具体来说,请参阅“行动中的类型约束”一节(iBook 中的 p621)。

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

一切都取决于您实施Equatable的类型。

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

  

“Swift标准库定义了一个名为Equatable的协议   需要任何符合类型来实现等于运算符(==)   并且不等于运算符(!=)来比较它的任何两个值   类型。 “

NSHipster有关于此主题的几个相关帖子:

Swift Default Protocol Implementations Swift Comparison Protocols

我还发现这个答案对于实现Equatable非常有用:

How do I implement Swift's Comparable protocol?

虽然它提到了可比较,但Equatable是一个子集,解释很好。

以上摘录自:Apple Inc.“The Swift Programming Language。”iBooks。 https://itun.es/gb/jEUH0.l

答案 4 :(得分:2)

另一个选择是使用过滤器:

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

这将检查数组haystack是否包含对象针。

答案 5 :(得分:1)

你做不到。这就是NSArray仍在那里的原因。但是,Apple文档的内容如下:StringNSString

  

Swift的String类型与Foundation的NSString无缝桥接   类。如果您正在使用Cocoa中的Foundation框架   Cocoa Touch,整个NSString API可以调用任何   除了描述的String功能外,您创建的字符串值   在这一章当中。您还可以将String值与任何API一起使用   需要一个NSString实例。

遵循这种方法,NSArray API } {/ 1}},但这不是因为原生Swift Array是原始的(大多数)可能是一个结构或类似的),所以你必须“转换”它到Array

答案 6 :(得分:1)

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

let     fruits: NSArray = [ "apple", "orange", "tomato (really?)" ]
let     index = fruits.indexOfObject("orange")

println("Index of Orange: \(index)")

答案 7 :(得分:-2)

如果您的数组元素是对象,并且您想在该数组中找到相同的对象,则可以使用此函数:

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
}