ios 我如何做 indexOfObject 或适当的 containsObject

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24010700/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:17:28  来源:igfitidea点击:

How do I do indexOfObject or a proper containsObject

iosarraysswift

提问by Daij-Djan

With an array: How do I do indexOfObjector a proper containsObject?

使用数组:我该怎么做indexOfObject或正确containsObject

I mean I know I could just bridge the Array to NSArrayand do it there ^^
But there must be a 'native' way of doing this

我的意思是我知道我可以将 Array 桥接到NSArray那里并在那里做 ^^
但必须有一种“本地”的方式来做到这一点

P.S. for the containsObjectI guess I could filter the array too but for indexOf?

PScontainsObject我想我也可以过滤数组但对于indexOf

回答by matt

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.)

您可以使用内置的find,从而避免桥接到 Objective-C — 但前提是您的元素类型是Equatable。(如果它不是 Equatable,您可以使用比较函数和扩展来实现。)

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 arris an Array<Piece>and pis a Piece.

现在您可以调用find(arr,p)where arris anArray<Piece>pis 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:

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

您也可以对 NSObject 子类执行此操作。例子:

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

Now you can call findon 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 findon 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.

现在你可以调用find一个 UIView 数组。但是,这有点麻烦,必须为每个您希望能够find在该类的 Array 上使用的类执行此操作。我已经向 Apple 提交了一份增强请求,要求将所有 NSObject 子类视为 Equatable 并且==应该isEqual:自动回退。

EDITStarting in Seed 3, this isautomatic for UIView and other NSObject classes. So findnow just works for them.

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

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

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

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

Alternatively, it takes a function that returns Bool:

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

let ix2 = s.indexOf {
extension RangeReplaceableCollectionType where Generator.Element : Equatable {
    mutating func removeObject(object:Self.Generator.Element) {
        if let found = self.indexOf(object) {
            self.removeAtIndex(found)
        }
    }
}
.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.

同样,这仅适用于 Equatable 的集合,因为显然你无法在大海捞针中找到针,除非你有办法识别针。

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

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

For example:

例如:

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

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

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

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

Oh, happy day!

哦,快乐的一天!

回答by Maximilian Litteral

Its actually able to be done in Swift. To get the index use find(YourArray, ObjectToFind)

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

回答by Daij-Djan

As I was told, this isn't available yet / I have to bridge it to NSArray

有人告诉我,这还不可用/我必须将它桥接到 NSArray

I don't like this and it feels dirty so I went and did this in an extension. that way it hides the usage of NSArray and allows apple to provide it later

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

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

https://gist.github.com/Daij-Djan/9d1c4b1233b4017f3b67

https://gist.github.com/Daij-Djan/9d1c4b1233b4017f3b67

回答by Max MacLeod

Apple provide an example of exactly this in the The Swift Programming Languagebook. Specifically, see the section on Type Constraints in Action (p621 in the iBook).

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

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

println("Index of Orange: \(index)")
== needle}).count > 0

Everything depends upon your type implementing Equatable.

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

The Swift Programming Language covers that and explains how to implement that protocol:

Swift Programming Language 涵盖了这一点并解释了如何实现该协议:

“The Swift standard library defines a protocol called Equatable, which requires any conforming type to implement the equal to operator (==) and the not equal to operator (!=) to compare any two values of that type. ”

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

NSHipsterhas a couple of relevant posts on this subject:

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

Swift Default Protocol ImplementationsSwift Comparison Protocols

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

I also found this answer very useful in implementing Equatable:

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

How do I implement Swift's Comparable protocol?

如何实现 Swift 的 Comparable 协议?

Alhough it mentions Comparable, Equatable is a subset and the explanation is good.

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

Excerpts above from: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/gb/jEUH0.l

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

回答by rmooney

One other option is to use filter:

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

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
}

This checks to see if array haystack contains object needle.

这会检查数组 haystack 是否包含对象 Needle。

回答by Leandros

You can't. That's why NSArrayis still there. However, the Apple documentation reads as follows about Stringand NSString:

你不能。这就是为什么NSArray仍然存在。但是,Apple 文档中关于String和的内容如下NSString

Swift's String type is bridged seamlessly to Foundation's NSString class. If you are working with the Foundation framework in Cocoa or Cocoa Touch, the entire NSString API is available to call on any String value you create, in addition to the String features described in this chapter. You can also use a String value with any API that requires an NSString instance.

Swift 的 String 类型无缝桥接到 Foundation 的 NSString 类。如果您在 Cocoa 或 Cocoa Touch 中使用 Foundation 框架,那么除了本章中描述的 String 功能之外,整个 NSString API 都可用于调用您创建的任何 String 值。您还可以将 String 值用于任何需要 NSString 实例的 API。

Following that approach, the NSArrayAPI shouldbe available on Array, but it isn't because the native Swift Arrayis a primitive (most likely a struct or similar), so you have to "convert"it to an NSArray.

按照这种方法,NSArrayAPI应该在 上可用Array,但这不是因为本机 SwiftArray是原始类型(很可能是结构或类似的),因此您必须将其“转换”NSArray.

回答by Ben Gottlieb

It appears that not all of the toll-free bridging from NS/CF space is in place. However, if you declare your array as an NSArray, it works fine:

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

##代码##

回答by phatmann

If your array elements are objects and you want to find an identical object in that array, you can use this function:

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

##代码##