Почему фильтры в 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)