Спасибо за этот вопрос. ??
Я протестировал обе функции, используя этот код на TIO:
let array = Array(0..<10_000_000)
do {
let start = Date()
let filtering = array.filter { $0 % 2 == 0 }
let end = Date()
print(filtering.count, filtering.last!, end.timeIntervalSince(start))
}
do {
let start = Date()
var removing = array
removing.removeAll { $0 % 2 == 0 }
let end = Date()
print(removing.count, removing.last!, end.timeIntervalSince(start))
}
(Чтобы иметь removing
и filtering
идентичны, закрытие, переданное removeAll
, должно было быть { $0 % 2 != 0 }
, но я не хотел давать преимущество ни одному фрагменту, используя оператор сравнения быстрее или медленнее.)
Идействительно, removeAll(where:)
быстрее, когда вероятность удаления элементов (назовем это Pr
) составляет 50%!Вот результаты тестов:
filter : 94ms
removeAll : 74ms
Это тот же самый случай, когда Pr
меньше 50% .
В противном случае фильтрация происходит быстрее для более высокого Pr
.
Следует иметь в виду, что в вашем коде list
является изменчивым, и это открывает возможность для случайных модификаций.
Лично я бы выбрал производительность вместо старых привычек, и, в некотором смысле, этот вариант использования более читабелен, поскольку намерение яснее.
Бонус: удаление на месте
Что означает удаление на месте - это замена элементов в массиве таким образом, что элементы кбыть удалены размещены после определенного индекса пивота.Элементы, которые нужно сохранить, - это элементы перед элементом поворота:
var inPlace = array
let p = inPlace.partition { $0 % 2 == 0 }
Имейте в виду, что partition(by:)
не сохраняет первоначальный порядок.
Этот подход часы лучше removeAll(where:)