Is there any difference at all between suffix(from:) and dropFirst(_:)?

心不动则不痛 提交于 2020-01-03 08:57:10

问题


It just occurred to me that when working with subsequences in Swift,

func suffix(from: Int) seems to be identical to just dropFirst(_:) (Obviously, you just change the input value from say "3" to "7" in the case of an array of length "10".)

Just to repeat that. So: of course, for an array of say length ten. What I mean is func suffix(from: Int) with "2" would be the same as dropFirst(_:) with "8", for example.

Similarly upTo / through seem to be identical to dropLast(_:)

Other than convenience is there any difference at all?

(Perhaps in error conditions, performance, or?)

I was wondering whether, in fact, inside Swift one or the other is just implemented by calling the other?


回答1:


They are completely different.

  • suffix(from:)

    • Defined by the Collection protocol.
    • Returns a Subsequence from a given starting Index.
    • Documented time complexity of O(1) (you can see its default implementation here).
    • Runtime error if the index you pass is out of range.
  • dropFirst(_:)

    • Defined by the Sequence protocol.
    • Returns a SubSequence with a given maximum number of elements removed from the head of the sequence.
    • Has a documented time complexity of O(n)*. Although its default implementation actually has a time complexity of O(1), this just postpones the O(n) walk through the dropped elements until iteration.
    • Returns an empty subsequence if the number you input is greater than the sequence's length.

*As with all protocol requirement documented time complexities, it's possible for the conforming type to have an implementation with a lower time complexity. For example, a RandomAccessCollection's dropFirst(_:) method will run in O(1) time.


However, when it comes to Array, these methods just happen to behave identically (except for the handling of out of range inputs).

This is because Array has an Index of type Int that starts from 0 and sequentially counts up to array.count - 1, therefore meaning that a subsequence with the first n elements dropped is the same subsequence that starts from the index n.

Also because Array is a RandomAccessCollection, both methods will run in O(1) time.




回答2:


Biggest difference IMO is that dropFirst() doesn't expose your code to out-of-range index errors. So you can safely use either form of dropFirst on an empty array, while the prefix / suffix methods can crash on an empty array or with out-of-range parameters.

So dropFirst() FTW if you'd prefer an empty array result when you specify more elements than are available rather than a crash, or if you don't want / need to check to make sure your the index you'll be using is less than the array.count, etc.

Conceptually, I think this makes sense for the operation as named, considering that first is an optional-typed property that returns the first element if it exists. Saying dropFirst(3) means "remove the maybe-present first element if it exists, and do so three times"




回答3:


You're right that they're connected, but yes there is a difference. From the docs:

let numbers = [1, 2, 3, 4, 5]
print(numbers.suffix(2))
// Prints "[4, 5]"
print(numbers.suffix(10))
// Prints "[1, 2, 3, 4, 5]"

versus

let numbers = [1, 2, 3, 4, 5]
print(numbers.dropFirst(2))
// Prints "[3, 4, 5]"
print(numbers.dropFirst(10))
// Prints "[]"

In the first example, suffix(2) returns only the last two elements, whereas dropFirst(2) returns all but the first two elements. Similarly, they behave differently wrt. arguments longer than the sequence is long. (Additionally, suffix will only work on finite sequences.)

Likewise with prefix and dropLast. Another way of thinking about it, for a sequence of length n, prefix(k) == dropLast(n-k), where k <= n.



来源:https://stackoverflow.com/questions/40333438/is-there-any-difference-at-all-between-suffixfrom-and-dropfirst

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!