How do I do indexOfObject or a proper containsObject

后端 未结 8 897
说谎
说谎 2020-12-03 03:00

With an array: How do I do indexOfObject or a proper containsObject?

I mean I know I could just bridge the Array to NSArray an

相关标签:
8条回答
  • 2020-12-03 03:57

    One other option is to use filter:

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

    This checks to see if array haystack contains object needle.

    0 讨论(0)
  • 2020-12-03 04:04

    You can use the built-in find, and thus avoid bridging to Objective-C — but only if your element type is Equatable. (If it isn't Equatable, you can make it so with a comparison function and an extension.)

    Example:

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

    Now you can call find(arr,p) where arr is an Array<Piece> and p is a Piece.

    Once you have this, you can develop utilities based on it. For example, here's a global function to remove an object from an array without bridging to 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
    }
    

    And test it like this:

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

    You can do this for NSObject subclasses too. Example:

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

    Now you can call find on an Array of UIView. It's sort of a pain in the butt, though, having to do this for every single class where you want to be able to use find on an Array of that class. I have filed an enhancement request with Apple requesting that all NSObject subclasses be considered Equatable and that == should fall back on isEqual: automatically.

    EDIT Starting in Seed 3, this is automatic for UIView and other NSObject classes. So find now just works for them.

    EDIT 2 Starting in Swift 2.0, indexOf will exist as a method:

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

    Alternatively, it takes a function that returns Bool:

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

    Again, this works only on collections of Equatable, since obviously you cannot locate a needle in a haystack unless you have a way of identifying a needle when you come to it.

    EDIT 3 Swift 2.0 also introduces protocol extensions. This means I can rewrite my global function removeObject as a method!

    For example:

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

    Since Array adopts RangeReplaceableCollectionType, now I can write code like this:

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

    Oh, happy day!

    0 讨论(0)
提交回复
热议问题