Разница между flatMap и compactMap в Swift

похоже, что в Swift 4.1 flatMap устарела. Однако есть новый метод в Swift 4.1 compactMap который делает то же самое? С flatMap вы можете преобразовать каждый объект в коллекции, а затем удалить все элементы, которые были нулевыми.
как flatMap

let array = ["1", "2", nil] 
array.flatMap {  } // will return "1", "2"

как compactMap

let array = ["1", "2", nil] 
array.compactMap {  } // will return "1", "2"

compactMap делает то же самое.

каковы различия между эти 2 метода? Почему Apple решила переименовать метод?

2 ответов


существует три различных варианта flatMap. Вариант Sequence.flatMap(_:), который принимает закрытие, возвращающее необязательное значение, устарел. Другие варианты flatMap (_:) как для последовательности, так и для опции остаются как есть. Причина, как поясняется в документе предложения, заключается в неправильном использовании.

устаревший flatMap функциональность варианта точно такая же при новом методе compactMap.

подробности здесь.


стандартная библиотека Swift определяет 3 перегрузки для flatMap функция:

Sequence.flatMap<S>(_: (Element) -> S) -> [S.Element]  
Optional.flatMap<U>(_: (Wrapped) -> U?) -> U?  
Sequence.flatMap<U>(_: (Element) -> U?) -> [U]  

последняя функция перегрузки может использоваться двумя способами:
Рассмотрим следующую структуру и массив:

struct Person {
  var age: Int
  var name: String
}  

let people = [Person(age: 21, name: "Osame"), Person(age: 17, name: "Masoud"), Person(age: 20, name: "Mehdi")]  

Первый способ: дополнительная упаковка и разворачивание:
Если вам нужно получить массив возрастов лиц, включенных в people array вы можете использовать две функции:

let flatMappedAges = people.flatMap({.age})  // prints: [21, 17, 20]
let mappedAges = people.map({.age})  // prints: [21, 17, 20]  

в этом случае будет делать работа и нет необходимости использовать flatMap, потому что оба дают один и тот же результат. Кроме того, в этом случае использования flatMap есть бесполезный процесс упаковки и разворачивания.(Параметр closure обертывает возвращаемое значение необязательным, а реализация flatMap разворачивает необязательное значение перед его возвращением)

Второй способ-соответствие строки протоколу сбора:
Думаю, вам нужно получить список имен людей из people массив. Вы можно использовать следующую строку :

let names = people.flatMap({.name})  

если вы используете версию swift до 4.0, вы получите преобразованный список

["Osame", "Masoud", "Mehdi"]  

но в более новых версиях String соответствует Collection протокол, Итак, ваше использование flatMap() будет соответствовать первой функции перегрузки вместо третьей и даст вам сплющенный результат ваших преобразованных значений:

["O", "s", "a", "m", "e", "M", "a", "s", "o", "u", "d", "M", "e", "h", "d", "i"]

заключение: они устарели третью перегрузку flatMap ()
Из-за этих злоупотреблений команда swift решила отказаться от третьей перегрузки функции flatMap. И их решение в том случае, когда вам нужно разобраться с Optionals до сих пор должен был ввести новую функцию под названием compactMap() что даст вам ожидаемый результат.