Почему фильтры в Swift дважды повторяют сборку?

Следующий код в Swift playground или Console App:

let letters = ["A", "B", "C"]

letters.filter({
    (x : String) -> Bool in
    println("PRINT: \(x)")
    return true
})

Распечатывает:

PRINT: A
PRINT: B
PRINT: C
PRINT: A
PRINT: B
PRINT: C

Почему он дважды перебирает коллекцию?

Ответ 1

Скорее всего, filter реализуется, чтобы сначала подсчитать количество элементов, которые необходимо сохранить, а затем, используя этот номер для распределения распределения памяти для нового массива, снова зацикливайтесь, чтобы скопировать те, которые ему нужно сохранить.

Тот факт, что он повторяется только один раз, если вы всегда возвращаете false, означает, что он оптимизирует второй цикл, если результат пуст.

Вы можете захотеть радаровать это как ошибку, но он, вероятно, "работает как запроектированный": в конце концов, массивы не являются списками.

Ответ 2

Он изменен в бета-версии 5. Теперь он перемещается только один раз, печатая ABC вместо ABCABC

Ответ 3

filter возвращает массив, который распечатывается игровой площадкой.

/// Return a Array containing the elements `x` of `self` for which
/// `includeElement(x)` is `true`
func filter(includeElement: (T) -> Bool) -> T[]

Я считаю, что (6 times) неверен, потому что, если вы посмотрите ниже, он true возвращается только 3 раза.

РЕДАКТОР. Вышеуказанное значение неверно.

Из-за игры с ним больше, я могу только сказать, что это просто поведение функции filter.

letters.reverse().filter({
    (x : String) -> Bool in
    println("PRINT: \(x)")
    return true
})

Это печатает CBACBA, поэтому он просто перебирает массив по порядку, дважды.

letters.filter({
        (x : String) -> Bool in
        println("PRINT: \(x)")
        if (x == "A") {
           return true
        }
        return false
    })

Это все еще печатает ABCABC, поэтому перейдите к рисунку.

Пойду спрошу у инженера Swift немного и вернусь к вам, почему это так! (Если они знают: p)