Xử lý Map, Filter, Reduce, Flatmap trong Swift

Introduction

Trong bài viết này tôi sẽ giới thiệu khái quát cách sử dụng các hàm map, flatmap, reduce, filter rất hữu ích trong swift khi xử lý với các đối tượng collection.

Map

Chạy 1 vòng lặp cho tất cả các phần tử trong collection và thực hiện phép toán giống nhau với từng phần tử đó. Ví dụ ta có sẵn 1 mảng, ta muốn tạo ra 1 mảng là mảng bình phương của từng phần tử trong mảng ban đầu Cách xử lý thông thường:

var numberArray = [1, 2, 3, 4, 5]
//traditional way 
var squareArray: [Int] = [ ]
for number in numberArray {
      squareArray.append(number * number) 
}
//Result: squareArray = [1, 4, 9, 16, 25]

Sử dụng Map

var numberArray = [1, 2, 3, 4, 5]

// Cach 1
var squareArray1 = numberArray.map({ (value: Int) -> Int in
      return value * value
})

//Cach 2
var squareArray2 = numberArray.map { (value: Int) in
      return value * value
}

//Cach 3
var squareArray3 = numberArray.map { value in 
      value * value
}

//Cach 4
var squareArray4 = numberArray.map { $0 * $0 }

Trong các ví dụ trên thì map nhận các closure là các argument và trả về kết quả như cách thực hiện vòng lặp thông thường 4 cách trên là 4 cách viết hàm map khác nhau, thực hiện thì như nhau

Filter

Lọc lấy ra mảng từ collection với các element thoả điều kiện nào đó, ví dụ như lấy ra mảng các số chẵn từ 1 mảng các số cho trước, lấy ra mảng các số chia hết cho 3 từ mảng cho trước, ... Ví dụ:

let numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

//Traditional way 
var evenNumberArray: [Int] = [ ]
for number in numberArray { 
      if (number %2 == 0) { 
            evenNumberArray.append(number)
      }
}

//Result: evenNumberArray = [2, 4, 6, 8, 10]

Sử dụng Filter

let numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let eventNumberArray = numberArray.filter { $0 %2 == 0 }

Reduce

Kết hợp tất cả các item trong 1 collection tạo ra 1 giá trị mới Ví dụ ta muốn tính tổng tất cả các phần tử trong mảng kiểu Int

var numbers = [1, 2, 3, 4, 5]
//Tradional way 
var sum = 0
for number in numbers {
      sum += number
}
//sum = 15

Sử dụng reduce

var numbers = [1, 2, 3, 4, 5]
//Reduce 
var sum1 = numbers.reduce(0, { $0 + $1 })
//sum1 = 15

var sum2 = number.reduce(0, +)
//sum2 = 15

Có thể sử dụng được cả với string

var stringArray = ["one", "two"] 
var oneTwo = stringArray.reduce("", +)

FlatMap

Khi thực hiện trên các sequences nó sẽ flattern collection của collections Ví dụ chúng ta có 1 mảng gồm 2 phần tử là 2 mảng, chúng ta muốn kết hợp 2 mảng này lại thành 1 mảng

let arrayInArray = [[1 ,2, 3], [4, 5, 6]]
var resultArray: [Int] = [ ]
for array in arrayInArray {
        resultArray += array 
}

//resultArray = [1, 2, 3, 4, 5, 6]

Sử dụng flatMap

let arrayInArray = [[1 ,2, 3], [4, 5, 6]]
let flattenedArray = arrayInArray.flatMap{ $0 }
// flattenedArray = [1, 2, 3, 4, 5, 6]

Hàm flatmap xoá nil khỏi collection Ví dụ:

let people: [String?] = ["A", nil, "B", nil, "C"] 
var validPeople = people.flatMap { $0 }
//varlidPeople = ["A", "B", "C"]

Chaining

Chúng ta có thể kết hợp các hàm ở trên lại với nhau Ví dụ ta muốn tính tổng bình phương của tất cả các số chẵn từ mảng của các mảng

let arrayInArray = [[1, 2, 3], [4, 5, 6]]
var resultValue = arrayInArray.flatMap{ $0 }.filter{ $0 %2 ==0 }.map{ $0 * $0}.reduce(0, +)
// resultValue = 56

Đầu tiên hàm flatMap{ $0 }tạo ra mảng [1, 2, 3, 4, 5, 6] sau đó hàm filter{ $0 %2 == 0} lấy ra các số chẵn [2, 4, 6] tiếp theo map { $0 * $0 } thực hiện bình phương [4, 16, 36] cuối cùng hàm reduce(0, +) sẽ tính tổng 4 + 16 + 36 = 56

Conclusion

Như vậy chỉ với rất ít dòng code ta đã thực hiện được rất nhiều các phép tính đối với các collection 1 cách đơn giản Tham khảo: https://medium.com/@mimicatcodes/simple-higher-order-functions-in-swift-3-0-map-filter-reduce-and-flatmap-984fa00b2532