Swift 无法使用“([Score], Score)”类型的参数列表调用 'find',其中 Score 是一个结构

Swift Cannot invoke 'find' with an argument list of type '([Score], Score)' where Score is a struct

虽然 find(["a", "b"], "c") 没有问题,但在尝试查找结构数组中的结构索引时出现错误:

struct Score
{
    //...
}

var scores: [Score] = //...
var score: Score = //...

find(self.scores, score) // Error: Cannot invoke 'find' with an argument list of type '([Score], Score)'

虽然这可能是默认情况下无法相互比较的结构的问题。但是将 Score 的定义更改为 class 给我同样的错误。

函数的接口 find is/was:

func find<C : CollectionType where C.Generator.Element : Equatable>(domain: C,
    value: C.Generator.Element) -> C.Index?

这表示 CCollectionType 必须具有 Equatable 的元素,而且 value 也必须是 Equatable

[注意 Swift 3.0:从 Swift 3.0 开始,您需要使用 index 函数,它有两个变化。首先,您将提供自己的谓词:

func index(where: (Self.Generator.Element) -> Bool) -> Self.Index?

第二,你的元素需要相等:

// Where Generator.Element : Equatable
func index(of: Self.Generator.Element) -> Self.Index?

如果您决定走 equatable 路线,则以下内容适用。 注完]

您的 Score 结构不是 Equatable,因此是错误。 你需要弄清楚分数相等是什么意思。也许是一些数字'score';也许它是 'score' 和 'user id'。这取决于您的 Score 抽象。一旦你知道,你实现 == 使用:

func == (lhs:Score, rhs:Score) -> Bool {
 return // condition for what it means to be equal
}

注意:如果您使用 class,因此得分为 'identity',那么您可以将其实现为:

func == (lhs:Score, rhs:Score) -> Bool { return lhs === rhs }

你的字符串示例有效,因为 StringEquatable。如果您查看 Swift 库代码,您会看到:

extension String : Equatable {}
func ==(lhs: String, rhs: String) -> Bool

正如其他人所说,您搜索的对象必须符合Equatable协议。

因此您需要向 Score 结构添加一个扩展,告诉编译器它符合该协议:

extension Score: Equatable {}

然后你需要为那个 class 实现 == 函数:

public func ==(lhs: Score, rhs: Score) -> Bool
{
  return lhs.whatever == rhs.whatever //replace with code for your struct.
}

编辑:从 Swift 2.0 开始,现在有一个内置版本的 find 需要一个闭包,因此您不必自己编写 – 而且,find 已重命名为 indexOf,现在是 CollectionType 的协议扩展,因此您可以像方法一样调用它:

// if you make `Score` conform to `Equatable:
if let idx = self.scores.indexOf(score) {

}

// or if you don't make it Equatable, you can just use a closure:
// (see original answer below for why you might prefer to do this)
if let idx = scores.indexOf({[=10=].scoreval == 3}) {

}

下面是 2.0 之前的原始答案


虽然建议您 class Equatable 的答案可能效果很好,但我建议您在选择这样做之前谨慎一些。原因是,正如文档所述,等同性意味着可替代性,并且您的 == 运算符必须是自反的、对称的和可传递的。如果不遵守这一点,在使用 equalssort 等算法时可能会出现一些非常奇怪的行为。如果在非最终 [=37] 上实现 Equatable 时要特别小心=]是的。如果你确定你能满足要求,那就去做吧,find就可以了。

如果没有,您可以考虑的替代方法是编写一个应该但不在标准库中的函数,这是一个find需要闭包:

func find<C: CollectionType>(source: C, match: C.Generator.Element -> Bool) -> C.Index {
    for idx in indices(source) {
        if match(source[idx]) { return idx }
    }
    return nil
}

有了这个之后,您可以提供您喜欢的任何匹配条件。例如,如果您的对象是 classes,您可以使用引用相等性:

let idx = find(scores) { [=12=] ===  }