FlatMap выдает предупреждение с массивом типа Int, но не с массивом типа String - PullRequest
4 голосов
/ 04 октября 2019

Когда я использую flatMap с массивом типа String, он не выдает никаких предупреждений, в то время как он выдает предупреждение в случае массива типа Int. Почему? Пример:

let strings = [
    "I'm excited about #SwiftUI",
    "#Combine looks cool too",
    "This year's #WWDC was amazing"
]
strings.flatMap{$0 + "."} //No warning

let ints = [
   2,3,4
]
ints.flatMap{$0 + 1} //'flatMap' is deprecated: Please use compactMap(_:) for the case where closure returns an optional value

1 Ответ

8 голосов
/ 04 октября 2019

Это потому, что это два разных flatMap метода.

Итак, прежде чем я отвечу на ваш вопрос, давайте вернемся назад и рассмотрим, что теперь намеревается сделать flatMap,а именно, применяя преобразование к последовательности и конкатенируя получающиеся последовательности. Типичный пример используется для «выравнивания» массивов массивов):

let arrayOfArrays = [[1, 2], [3, 4, 5]]
let array = arrayOfArrays.flatMap { $0 }
print(array)

В результате:

[1, 2, 3, 4, 5]

flatMap свел массив массивов в один массив.

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

Рассмотрим:

let input: [Int?] = [0, 1, nil, 3]
let results = input.flatMap { $0 } // 'flatMap' is deprecated: Please use compactMap(_:) for the case where closure returns an optional value
print(results)

В результате:

[0, 1, 3]

Итак, мы должны заменить flatMap на compactMap в соответствии с рекомендациями:

let input: [Int?] = [0, 1, nil, 3]
let results = input.compactMap { $0 }
print(results)

Это даст нам желаемый результат без предупреждения.


Итак, давайте вернемся к вашим примерам. Поскольку строки - это массивы символов, вам понадобится слово и сгладит его:

let strings = [
    "I'm excited about #SwiftUI",
    "#Combine looks cool too",
    "This year's #WWDC was amazing"
]
let stringResults = strings.flatMap { $0 + "." }
print(stringResults)

В результате получится массив символов:

["I "," \ '"," m "," "," e "," x "," c "," i "," t "," e "," d "," "," a ","b", "o", "u", "t", "", "#", "S", "w", "i", "f", "t", "U", "I", ".", "#", "C", "o", "m", "b", "i", "n", "e", "", "l", "o", "o"," k "," s "," "," c "," o "," o "," l "," "," t "," o "," o ",". "," T"," h "," i "," s "," "," y "," e "," a "," r "," \ '"," s "," "," # ","W "," W "," D "," C "," "," w "," a "," s "," "," a "," m "," a "," z ","i "," n "," g ",". "]

Это явно не то, что вы хотели, но компилятор поверил вам на слово, что вы хотите сгладить массив массива символов(то есть массив строк) в плоский массив символов. Вот почему не было никаких предупреждений.


Само собой разумеется, в ваших примерах вы не использовали бы ни flatMap (потому что вы не имеете дело с массивами массивов), ни compactMap (потому чтовы не имеете дело с опциями). Вы бы просто использовали map:

let strings = [
    "I'm excited about #SwiftUI",
    "#Combine looks cool too",
    "This year's #WWDC was amazing"
]
let stringsResults = strings.map { $0 + "." }
print(stringsResults)

let ints = [2, 3, 4]
let intsResults = ints.map { $0 + 1 }
print(intsResults)

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

Этот flatMap метод на Optional «Оценивает данное замыкание, когда это *Экземпляр 1074 * не является nil, передавая развернутое значение в качестве параметра ». Но если необязательным было nil, этот flatMap также вернет nil.

Например:

func message(for value: Int?) -> String? {
    return value.flatMap { "The value is \($0)" }
}

Таким образом, если value было 42, результатом будет необязательная строка, "The value is 42". Но если value было nil, то результатом будет nil.

Это представление flatMap не относится к рассматриваемому вопросу, но я хотел упомянуть его для полноты картины.

...