Swift 數組中 Map,FlatMap,Filter,Reduce的使用
來自: http://www.cocoachina.com/swift/20160210/15068.html
map函數能夠被數組調用,它接受一個閉包作為參數,作用于數組中的每個元素。閉包返回一個變換后的元素,接著將所有這些變換后的元素組成一個新的數組
1. 比如我們有一個這樣的需求遍歷一個數組中所有的元素,將每個元素自身與自身相加,最后返回一個保存相加后元素的數組(-_-原諒我這表達能力,下面用代碼闡述)
如果我們不使用map函數,那么代碼如下
let numbers = [1,2,3] var sumNumbers = [Int]() for var number in numbers { number += number sumNumbers.append(number) } // [2,4,6] print(sumNumbers)
可以看到上面的代碼正是我們經常用到的代碼,但通過數組的map函數可以幫我們簡化上面的代碼
// 可以看到我們甚至可以不再定義可變的數組直接用不可變的就可以 let numbers = [1,2,3] let sumNumbers = numbers.map { (number: Int) -> Int in return number + number } // 下面介紹簡便寫法 因為map閉包里面的類型可以自動推斷所以可以省略 let sumNumbers1 = numbers.map { number in return number + number } // 可以省了return 但是循環次數多了一次 目前不知道這是什么原因(循環次數是3次這是4次) 結果是一樣的 let sumNumbers2 = numbers.map { number in number + number } print(sumNumbers2) // [2,4,6] // 最終簡化寫法 let sumNumbers3 = numbers.map { $0 + $0 }
2. Map函數返回數組的元素類型不一定要與原數組相同
let fruits = ["apple", "banana", "orange", ""] // 這里數組中存在一個""的字符串 為了后面來比較 map 和 flatMap let counts = fruits.map { fruit -> Int? in let length = fruit.characters.count guard length > 0 else { return nil } return length } // [Optional(5), Optional(6), Optional(6), nil] print(counts)
3. Map還能返回判斷數組中的元素是否滿足某種條件的Bool值數組
let array = [1,2,3,4,5,6] // 最潔簡的寫法 let isEven = array.map { $0 % 2 == 0 } // 這里在寫下完成的寫法 下面的例子 將都采用最潔簡的寫法^_^ 同時也要養成習慣看見上面那種潔簡的寫法 就要懂它做了些什么 會有什么樣的結果 let isEven1 = array.map { num in // 寫上retrun在Playground中的循環次數是6次 不寫是7次 Xcode版本是7.2(7C68) // 不知道這是不是bug 有知道的提醒下我~ return num % 2 == 0 } // [false, true, false, true, false, true] print(isEven)
FlatMap
flatMap 與 map 不同之處是
flatMap返回后的數組中不存在 nil 同時它會把Optional解包;
flatMap 還能把數組中存有數組的數組 一同打開變成一個新的數組 ;
flatMap也能把兩個不同的數組合并成一個數組 這個合并的數組元素個數是前面兩個數組元素個數的乘積
</div>
1. flatMap返回后的數組中不存在nil 同時它會把Optional解包
let fruits = ["apple", "banana", "orange", ""] let counts = fruits.flatMap { fruit -> Int? in let length = fruit.characters.count guard length > 0 else { return nil } return length } // [5,6,6] print(counts)
2. flatMap 還能把數組中存有數組的數組 一同打開變成一個新的數組(看代碼秒懂~_~)
let array = [[1,2,3], [4,5,6], [7,8,9]] // 如果用map來獲取新的數組 let arrayMap = array.map { $0 } // [[1, 2, 3], [4, 5, 6], [7, 8, 9]] print(arrayMap) // 用flatMap let arrayFlatMap = array.flatMap { $0 } // [1, 2, 3, 4, 5, 6, 7, 8, 9] print(arrayFlatMap)
3. flatMap也能把兩個不同的數組合并成一個數組 這個合并的數組元素個數是前面兩個數組元素個數的乘積
// 這種情況是把兩個不同的數組合并成一個數組 這個合并的數組元素個數是前面兩個數組元素個數的乘積 let fruits = ["apple", "banana", "orange"] let counts = [1, 2, 3] let fruitCounts = counts.flatMap { count in fruits.map { fruit in // title + "(index)" // 也可以返回元組 (fruit, count) } } // [("apple", 1), ("banana", 1), ("orange", 1), ("apple", 2), ("banana", 2), ("orange", 2), ("apple", 3), ("banana", 3), ("orange", 3)] print(fruitCounts) // 這種方法估計用的很少 可以算是一個 flatMap 和 map 的結合使用吧
Filter
filter 可以取出數組中符合條件的元素 重新組成一個新的數組
filter可以很好的幫我們把數組中不需要的值都去掉 這個很贊!
let numbers = [1,2,3,4,5,6] let evens = numbers.filter { $0 % 2 == 0 } // [2, 4, 6] print(evens)
Reduce
map,flatMap和filter方法都是通過一個已存在的數組,生成一個新的、經過修改的數組。然而有時候我們需要把所有元素的值合并成一個新的值 那么就用到了Reduce
1. 比如我們要獲得一個數組中所有元素的和
let numbers = [1,2,3,4,5] // reduce 函數第一個參數是返回值的初始化值 let sum = numbers.reduce(0) { $0 + $1 } // 這里我寫下完整的格式 let sum1 = numbers.reduce(0) { total, num in // 這里寫不寫return在Playground都循環5次 但上面用最潔簡的方法顯示循環6次。。。 What The Fuck 這是什么鬼!!! return total + num } // 15 print(sum)
2. 合并成的新值不一定跟原數組中元素的類型相同
let numbers = [1,5,1,8,8,8,8,8,8,8,8] // reduce 函數第一個參數是返回值的初始化值 let tel = numbers.reduce("") { "($0)" + "($1)" } // 15188888888 print(tel)
3. ruduce 還可以實現 map 和 filter 并且時間復雜度變為O(n) 原來 map 和 filter 的時間復雜度是O(n*n)
extension Array { func mMap (transform: Element -> U) -> [U] { return reduce([], combine: { $0 + [transform($1)] }) } func mFilter (includeElement: Element -> Bool) -> [Element] { return reduce([]) { includeElement($1) ? $0 + [$1] : $0 } } }
本人對泛型的研究還很淺顯,后續我會寫一篇關于Swift范型的文章,歡迎大家關注 -> MelodyZhy
</div> 本文由用戶 yqud1891 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!