What is the difference between filter(_:).first and first(where:)?

后端 未结 2 1772
执笔经年
执笔经年 2020-12-22 03:18

Please consider the following strings array:

let strings = [\"str1\", \"str2\", \"str10\", \"str20\"]

Let\'s assume that what required is t

相关标签:
2条回答
  • 2020-12-22 03:54

    I believe we should start from considering each method separately and their purpose.

    filter(_:) is not purposefully designed to prepare us to obtain first element. It is about filtering and that's it. It merely returns us a sequence. first can be used after filter, but that's just an instance of usage, a possible case. first is called for a collection and if we want, of course we are free to use it directly after filter.

    But first(where:) was designed to filter and return a single element and is evidently the go-to approach to accomplish that kind of a task. That said, it is easy to presume that it's also preferred from performance perspective. As mentioned, we filter entire sequence, but with first(where:) we only process the portion of a sequence until condition is met.

    0 讨论(0)
  • 2020-12-22 03:55

    You are correct in observing that filter(_:) returns all elements that satisfy a predicate and that first(where:) returns the first element that satisfy a predicate.

    So, that leaves us with the more interesting question of what the difference is between elements.filter(predicate).first and elements.first(where: predicate).

    As you've already noticed they both end up with the same result. The difference is in their "evaluation strategy". Calling:

    elements.filter(predicate).first
    

    will "eagerly" check the predicate against all elements to filter the full list of elements, and then pick the first element from the filterer list. By comparison, calling:

    elements.first(where: predicate)
    

    will "lazily" check the predicate against the elements until it finds one that satisfies the predicate, and then return that element.

    As a third alternative, you can explicitly use "a view onto [the list] that provides lazy implementations of normally eager operations, such as map and filter":

    elements.lazy.filter(predicate).first
    

    This changes the evaluation strategy to be "lazy". In fact, it's so lazy that just calling elements.lazy.filter(predicate) won't check the predicate against any elements. Only when the first element is "eagerly" evaluated on this lazy view will it evaluate enough elements to return one result.


    Separately from any technical differences between these alternatives, I'd say that you should use the one that most clearly describes your intentions. If you're looking for the first element that matches a criteria/predicate then first(where:) communicates that intent best.

    0 讨论(0)
提交回复
热议问题