web-dev-qa-db-ja.com

Swift:フィルター関数を使用してフィルターした後、indexOfを呼び出している間、型の値を@noescapeに変換できません

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

私は何を間違っていますか?理解できません。 :/

私の目的は、そのアイテムのインデックスを見つけることです。私は代替ソリューションを開くと思いますが、これは「正しい方法」だと思うので、もちろんこれが推奨されます。

18
Dima Deplov

Swift配列のindexOfメソッドは、配列の型と一致する型のオブジェクトを取得しません。代わりに、クロージャーを取得します。このクロージャーは、配列の型の要素を取得し、ブール値を返します。

したがって、実際には、結果のarrayが実際に必要な場合を除き、filterの呼び出しに煩わされることはありません(すべきではありません)。フィルターをかけているテストに合格する最初のオブジェクトを探しているだけの場合...まったく同じテストをindexOfに渡します。

したがって、物事を単純に保つために、文字列の配列があり(それらはすべて、繰り返しの多い1文字の文字列であるとしましょう)、文字列_"a"_ではなく、文字列の最初のインデックスを検索したい場合は、 _"a"_である文字列に配列をフィルタリングし、firstメソッドでそのテストに合格した最初の文字列を見つけ、その正確なオブジェクトのインデックスを見つける代わりに、そのテストに合格しますindexOfメソッドに:

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

let index = letters.indexOf {
    $0 == "a"
}
_

明確にするために、場合によっては、個々の要素を渡してそれを探すだけでうまくいくように見えます。おそらく、SwiftのEquatableプロトコルへの準拠に依存しています。たとえば、使用されているletters.indexOf("a")ここで、コンパイラーは満足していました。しかし、すべての配列がEquatableに準拠するものを保持するために必要であるとは限らず、配列はその要素を比較する方法について仮定を立てることができません。これらの場合、クロージャーを渡す上記の例を使用する必要があります。最初にフィルタリングしてからindexOfを呼び出すのではなく、このクロージャーをindexOfに渡すことはおそらく注意する価値があります配列がletters.indexOf("a")アプローチを許可している場合でも、とにかく非常に効率的です。たとえば、より複雑な文字列があり、文字「a」で始まる最初の文字列が欲しいだけの場合、これは遠いでしょう、元の配列を「a」で始まる文字列の配列にフィルタリングすることから始めるよりもはるかに効率的です。

26
nhgrif