J'ai environ 2000 éléments dans mon tableau, et quand il est filtré, je voudrais terminer le filtrage dès que j'ai 5 éléments dans mon tableau filtré.
Actuellement c'est:
providerArray.filter({($0.lowercased().range(of:((row.value as? Ssortingng)?.lowercased())!) != nil)})
qui peut returnner jusqu'à 2000 résultats ce qui est un gaspillage de traitement, et le time.
Pour être plus clair, j'ai besoin d'une solution qui équivaut à limiter les résultats du filter comme je le peux avec les récupérations de coreData [request setFetchLimit:5];
La solution la plus rapide en termes de time d'exécution semble être une boucle explicite qui ajoute des éléments correspondants jusqu'à ce que la limite soit atteinte:
extension Sequence { public func filter(where isIncluded: (Iterator.Element) -> Bool, limit: Int) -> [Iterator.Element] { var result : [Iterator.Element] = [] result.reserveCapacity(limit) var count = 0 var it = makeIterator() // While limit not reached and there are more elements ... while count < limit, let element = it.next() { if isIncluded(element) { result.append(element) count += 1 } } return result } }
Exemple d'utilisation:
let numbers = Array(0 ..< 2000) let result = numbers.filter(where: { $0 % 3 == 0 }, limit: 5) print(result) // [0, 3, 6, 9, 12]
Vous pouvez également utiliser .lazy
pour booster un peu les performances:
let numbers: [Int] = Array(0 ..< 2000) let result: AnySequence = numbers .lazy .filter { print("Calling filter for: \($0)") return ($0 % 3) == 0 } .prefix(5) print(Array(result))
Cela appellera la fonction de filter
seulement pour les 15 premières valeurs (jusqu'à ce qu'il trouve 5 qui passent le filter).
Vous pouvez maintenant vous concentrer sur l'amélioration des performances du filter
lui filter
même. Par exemple en mettant en cache des valeurs. Vous n'avez pas à le faire, mais si certaines valeurs ne cessent de se répéter, cela peut améliorer considérablement les performances.
let numbers: [Int] = Array(0 ..< 2000) var filterCache: [Int: Bool] = [:] let result: AnySequence = numbers .lazy .filter { if let cachedResult = filterCache[$0] { return cachedResult } print("Calling filter for: \($0)") let result = (($0 % 3) == 0) filterCache[$0] = result return result } .prefix(5) print(Array(result))
Vous pouvez appliquer cette méthode directement à votre fonction.
Notez également que pour améliorer les performances, vous devez:
save ((row.value as? Ssortingng)?.lowercased())!
dans une variable locale car elle est exécutée plusieurs fois
simplifier l'expression en utilisant les options:
let result: AnySequence = providerArray .lazy .filter { $0.range(of: row.value as! Ssortingng, options: [.caseInsensitive]) != nil } .prefix(5)