Search code examples
iosswiftnspredicate

Limit the results of a Swift array filter to X for performance


I have about 2000 elements in my array, and when it is filtered, I would like to end the filtering as soon as I have 5 elements in my filtered array.

Currently it is:

providerArray.filter({($0.lowercased().range(of:((row.value as? String)?.lowercased())!) != nil)})

which can return up to 2000 results which is a waste of processing, and time.

To be more clear, I need a solution that is equivalent to limiting the filter results like I can with coreData fetches [request setFetchLimit:5];


Solution

  • The fastest solution in terms of execution time seems to be an explicit loop which adds matching elements until the limit is reached:

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

    Example usage:

    let numbers = Array(0 ..< 2000)
    let result = numbers.filter(where: { $0 % 3 == 0 }, limit: 5)
    print(result) // [0, 3, 6, 9, 12]