Collection count predicates


I've noticed in my code that I often want to test a Collection's count without really caring about the exact value. For example, to check that a collection is has at least n elements, or exactly n elements. The typical way to write this would be something like:

if someString.count > 4 { /* do something */ }

extension Character {
  var isDecimalScalar: Bool {
    return unicodeScalars.count == 1 &&
           (48...57).contains(unicodeScalars.first!.value) // Unicode scalar values for 0...9.

However, String.count is O(n) - it will traverse the entire string and return an exact value, which I don't particularly care about. The lazy Character.UnicodeScalars view might be converting UTF-16 encoded characters to UInt32 unicode scalars or whatever in order to calculate its count. Much of this work is pointless; the predicate can often return early.

It's just an idea - I thought I'd throw it out there. Do people think this problem is worth solving in the standard library? I sketched out an idea of how it might look:

1 Like

May as well have a .lessThan() predicate. I prefer colleciton.count(is: lessThan(x)) over !collection.count(is: greaterThan(x)), imo.

1 Like

!collection.dropFirst(4).empty isn't too bad for the "at least" case. The "exactly" case is a little trickier: collection.prefix(5).count == 4 is the best I can do. So maybe it's needed, maybe not.

1 Like

I'm thinking that you probably wouldn't need to write this directly. The compiler could detect when you're comparing a Collection's count to something (rather than storing it) and rewrite it for you.

Maybe this could just be an optimisation in the standard library - maybe it doesn't even need to be public API. The only reason for making it public would be if some non-RandomAccessCollections could answer the predicate more efficiently...


Well, I prefer to know, what really is going on.

Did you encounter a situation where this had relevant impact on the observable behaviour of your program or is this an exercise in code golfing ?

This also matches the Comparable protocol.

Would this work nicely with the new count(where:) filtering? I could see these features being used in conjuction