Swift:在使用filter函数进行过滤后,调用indexOf时无法将type的值转换为@noescape

Dim*_*lov 18 arrays casting filter indexof swift

在Swift 2中,我收到一个错误:

无法将类型的值转换'[String:AnyObject]'为预期的参数类型'@noescape ([String:AnyObject])'throws - > Bool"

//today = NSDate()
//array : [[String:AnyObject]]
// I use if let because of we might now get element in the array matching our condition

if let elementOfArray = array.filter({$0["id"] as? Int == anotherDictionary["matchID"] as? Int && ($0["nextFireDate"] as? NSDate)?.compare(today) == NSComparisonResult.OrderedAscending}).first {

   let index = array.indexOf(elementOfArray) // error here
}
Run Code Online (Sandbox Code Playgroud)

我做错了什么?我无法理解.:/

我的目标是找到那个项目的索引,我认为我开放替代解决方案,但当然这个是首选,因为我认为这是"正确的方法".

nhg*_*rif 26

indexOfSwift数组上的方法不接受与数组类型匹配的类型的对象.相反,它需要一个关闭.该闭包采用数组类型的元素并返回一个bool.

所以,实际上,filter除非我们确实需要结果数组,否则我们不会(也不应该)甚至打扰调用.如果我们只是在寻找第一个通过你要过滤的测试的对象......那么我们只需要通过相同的测试即可indexOf.

所以,为了简单起见,如果我们有一个字符串数组(并且假设它们都是具有大量重复的单字母字符串),并且我想找到字符串的第一个索引"a",而不是将数组过滤到字符串"a",然后找到第一个使用该first方法传递该测试的字符串,然后找到该确切对象的索引,相反,我只是将该测试传递给该indexOf方法:

let letters: [String] = ["x", "y", "z", "a", "b", "c"]

let index = letters.indexOf {
    $0 == "a"
}
Run Code Online (Sandbox Code Playgroud)

为清楚起见,似乎只是简单地传递单个元素并在某些情况下查找它.它可能依赖于Swift Equatable协议的一致性.例如,我可以简单地使用letters.indexOf("a")这里.编译器会很高兴.但显然,并不是每个数组都需要保存符合的东西Equatable,并且数组不能对如何比较其元素做出假设.在这些情况下,您将不得不使用上面传递闭包的示例.值得注意的是,即使你的数组​​允许这种方法,传递这个闭包indexOf而不是先进行过滤然后调用indexOf将会非常高效letters.indexOf("a").例如,如果我有更复杂的字符串,并且我只想要以字母'a'开头的第一个字符串,这将比通过将原始数组过滤到以'开头'开头的字符串数组开始更有效率.一个'.

  • 有两个*indexOf方法,一个采用元素,一个采用谓词.`["x","y","z","a","b","c"] .indexOf("a")`编译没有问题. (2认同)
  • @MartinR确实.我在那里添加了一个大脚注.我相当自信"简单"只适用于`Equatable`类型(这解释了为什么flinth可能看不到它).但另外,正如我所解释的那样,即使对于"Equatable"类型,也有一些情况下你不想忽略谓词重载. (2认同)