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?
这表示 C
的 CollectionType
必须具有 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 }
你的字符串示例有效,因为 String
是 Equatable
。如果您查看 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
的答案可能效果很好,但我建议您在选择这样做之前谨慎一些。原因是,正如文档所述,等同性意味着可替代性,并且您的 ==
运算符必须是自反的、对称的和可传递的。如果不遵守这一点,在使用 equals
、sort
等算法时可能会出现一些非常奇怪的行为。如果在非最终 [=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=] === }
虽然 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?
这表示 C
的 CollectionType
必须具有 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 }
你的字符串示例有效,因为 String
是 Equatable
。如果您查看 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
的答案可能效果很好,但我建议您在选择这样做之前谨慎一些。原因是,正如文档所述,等同性意味着可替代性,并且您的 ==
运算符必须是自反的、对称的和可传递的。如果不遵守这一点,在使用 equals
、sort
等算法时可能会出现一些非常奇怪的行为。如果在非最终 [=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=] === }