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

2019-06-17 03:12发布

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?

2条回答
够拽才男人
2楼-- · 2019-06-17 03:43

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.

查看更多
ら.Afraid
3楼-- · 2019-06-17 03:44

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.

查看更多
登录 后发表回答