2015-10-30 5 views
18

In Swift 2, Ich erhalte eine Fehlermeldung:Swift: kann nicht Wert vom Typ konvertieren, während Anruf indexOf @noescape, nachdem Filter mit Filterfunktion

Cannot convert value of type '[String:AnyObject]' to expected argument type '@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 
} 

Was ich falsch? Ich kann es nicht verstehen. :/

Mein Ziel ist es, den Index dieses Artikels zu finden, ich denke, dass ich für alternative Lösungen öffne, aber natürlich wird dieser bevorzugt, weil ich denke, dass dies der "richtige Weg" ist.

+0

Wie sieht der eigentliche Code anstelle des '...' aus? Ich weiß nicht, ob es wichtig ist, aber es könnte hilfreich sein, wenn jemand genau das kopieren und einfügen könnte, was du auf einen Spielplatz hast, um den genauen Fehler zu sehen. – nhgrif

+0

@nhgrif Ich denke, das ist egal, in wenigen Worten findet dieser Code genau eine Zeile nach Wörterbuch Schlüssel/Wert-Übereinstimmung. –

+0

Es ist wahrscheinlich nicht wichtig, aber Swift erlaubt uns, so viel in so wenig zu verdichten. Die Fragen sollten so detailliert wie das genaue Problem sein. Ich spiele selbst auf einem Spielplatz damit. Wir können die Gesamtheit des 'if let' tatsächlich entfernen. Sie sollten diese Frage wirklich vereinfachen, wo nur der 'indexOf'-Aufruf und der tatsächlich erzeugte Fehler die Frage sind. – nhgrif

Antwort

26

Die Methode indexOf auf Swift-Arrays akzeptiert kein Objekt eines Typs, der dem Array-Typ entspricht. Stattdessen braucht es eine Schließung. Diese Schließung nimmt ein Element vom Typ des Arrays und gibt ein bool zurück.

Also, tatsächlich, wir nicht (und sollte nicht) sogar mit der filter Aufruf zu stören, es sei denn, wir benötigen tatsächlich die resultierende Array. Wenn wir nur nach dem ersten Objekt suchen, das den Test, für den Sie filtern, besteht, dann übergeben wir genau den gleichen Test an indexOf.

Also, um die Dinge einfach zu halten, wenn wir eine Reihe von Zeichenfolgen haben (und sagen wir, sie sind alle Buchstabenfolgen mit vielen Wiederholungen), und ich möchte den ersten Index der Zeichenfolge "a" statt Filtern des Array nach unten Strings, die "a" sind, dann die erste Zeichenfolge zu finden, die diesen Test mit dem first Methode übergeben, und dann wird der Index dieses genaue Objekt zu finden, statt, gebe ich nur diesen Test in das indexOf Methode:

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

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

Für die Klarheit, es erscheint Rs, die einfach ein einzelnes Element passieren und danach suchen, funktionieren in einigen Fällen. Es beruht wahrscheinlich auf der Übereinstimmung mit dem Protokoll Equatable von Swift. Ich hätte zB letters.indexOf("a") hier vereinfacht verwenden können. Der Compiler wäre glücklich gewesen. Aber offensichtlich ist nicht jedes Array zusammengesetzt, das benötigt wird, um Dinge zu halten, die Equatable entsprechen, und das Array kann keine Annahmen treffen, wie man seine Elemente dann vergleicht. In diesen Fällen müssen Sie das obige Beispiel für die Übergabe eines Abschlusses verwenden. Es ist wahrscheinlich erwähnenswert, dass die Übergabe dieser Schließung an indexOf eher als zuerst Filterung und dann Aufruf indexOf sowieso ungeheuer effizienter wird, auch wenn Ihr Array den letters.indexOf("a") Ansatz ermöglicht. Wenn ich zum Beispiel komplexere Strings hätte, und ich wollte nur den ersten String, der mit dem Buchstaben 'a' begonnen hat, wäre das weit, viel effizienter als das Filtern des ursprünglichen Arrays auf ein String-Array, beginnend mit ' ein'.

+0

fast! Oh, sieht so aus als wäre das die Antwort. –

+2

Es gibt * zwei * indexOf-Methoden, wobei eine ein Element und eine ein Prädikat verwendet. '[" x "," y "," z "," a "," b "," c "]. indexOf (" a ")' kompiliert ohne Probleme. –

+0

@MartinR, aber das ist zumindest kein Wörterbuch. –