How to get the count of a type conforming to `Sequ

2019-06-17 03:05发布

问题:

Let's say I have this code:

func work<S: Sequence>(sequence: S) {
    // do stuff
}

How could I figure out how many elements there are in sequence?
The obvious version I'd go for is pretty inefficient:

var count = 0
for element in sequence {
    count += 1
}

There must be a nicer way, right?

回答1:

I do not think that there is a better method for an arbitrary type conforming to SequenceType. The only thing that is known about a sequence is that is has a generate() method returning a GeneratorType, which in turn has a next() method. The next() method advances to the next element of the sequence and returns it, or returns nil if there is no next element.

Note that it is not required at all that next() eventually returns nil: a sequence may have "infinite" elements.

Therefore enumerating the sequence is the only method to count its elements. But this need not terminate. Therefore the answer could also be: A function taking a sequence argument should not need to know the total number of elements.

For types conforming to CollectionType you can use the countElements() function (renamed to count() in Swift 1.2).

There is also underestimateCount():

/// Return an underestimate of the number of elements in the given
/// sequence, without consuming the sequence.  For Sequences that are
/// actually Collections, this will return countElements(x)
func underestimateCount<T : SequenceType>(x: T) -> Int

but that does not necessarily return the exact number of elements.



回答2:

A more "functional" approach would be:

let count = sequence.reduce(0) { acc, row in acc + 1 }

Or even make an extension:

extension Sequence {
    var count: Int { return reduce(0) { acc, row in acc + 1 } }
}

let count = sequence.count

Note This does still suffer from the basic sequence problem that you have to consume the sequence to count it.