Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Những điều cần nhớ khi sử dụng scala flatMap
Ở scala có một hàm hay được dùng cho Collection gọi là flatMap
. Hàm này có nhiều tác dụng khá thú vị, tuy nhiên cũng có nhiều hành vi khá khó đoán trước. Bài viết này tổng hợp lại các hành vi đó của flatMap
Cơ bản
Cách sử dụng của flatMap khá đơn giản, có thể hiểu thông qua ví dụ sau:
Seq(Seq(1,2,3), Seq(4), Seq(5, 6)) flatMap { x => x }
sẽ cho kết quả là
Seq(1,2,3,4,5,6)
Một ví dụ khác:
Seq(Seq(1,2,3), Seq(), Seq(5, 6)) flatMap { x => x }
sẽ cho kết quả là
Seq(1,2,3,5,6)
Từ ví dụ trên có thể thấy scala loại bỏ các giá trị rỗng (Seq(), hoặc trong trường hợp khác có thể là None hoặc Any)
Một cách đơn giản, hàm flatMap là kết hợp của 2 hàm flatten
và Map
Một số hành vi / tính năng thú vị của flatMap
Ví dụ 1
Seq(Seq(1,2,3), Seq(), Seq(5,6)) flatMap { x => x.size }
Hãy đoán xem đoạn code trên sẽ cho kết quả là gì :D.
Chắc hẳn nhiều bạn sẽ đoán kết quả là Seq(3,0,2)
, hay chính là độ dài của 3 input Sequence.
Tuy nhiên thử chạy đoạn code trên:
scala> Seq(Seq(1,2,3), Seq(), Seq(5,6)) flatMap { x => x.size }
<console>:9: error: type mismatch;
found : Int
required: scala.collection.GenTraversableOnce[?]
Seq(Seq(1,2,3), Seq(), Seq(5,6)) flatMap { x => x.size }
^
scala phàn nàn là block bên trong flatMap nên trả về kiểu GenTraversableOnce
, trong khi chúng ta lại trả về biến Int
Trong những tình huống thế này chúng ta nên dùng map
thay cho flatMap
.
Tuy nhiên nếu vẫn muốn sử dụng flatMap, chúng ta có thể làm như sau:
Seq(Seq(1,2,3), Seq(), Seq(5,6)) flatMap { x => Some(x.size) }
Ví dụ 2
Hãy hình dung kết quả trả về của đoạn code:
Seq(Seq("hello", "world"), Seq("good", "morning")) flatMap { x => x.mkString(" ").toUpperCase }
Chắc hẳn sẽ có nhiều bạn đoán là :
Seq("HELLO WORLD", "GOOD MORNING")
Tuy nhiên chạy thử trên console chúng ta thu được kết quả:
Seq(H, E, L, L, O, , W, O, R, L, D, G, O, O, D, , M, O, R, N, I, N, G)
Vậy điểm đặc biêt ở đây là gì, đó chính là tính chất đặc biệt của String:
val x: scala.collection.GenTraversableOnce[Char] = "hello"
Thế nên một cách đơn giản,
Seq(Seq("hello", "world"), Seq("good", "morning"))
sẽ tương đương với
Seq(Seq(Seq("h","e","l","l","o")....))
Ví dụ 3
Seq(1,2,3,4) flatMap { x =>
if(x % 2 == 0) Some(x) else None
} map { x =>
x * 2
} foreach {
println
}
Đoạn code trên cho kết quả là
4, 8
Kết quả này không quá khó để hình dung. Để có được kết quả tương tự như trên chúng ta có thể dùng for loop, hoặc là map + filter cũng cho kết quả tương tự. Tuy nhiên chúng ta có thể thấy được từ ví dụ trên là để map block với flatMap, chúng ta phải trả về Some
.







