Trong phần trước chúng ta đã cùng tìm hiểu về các khái niệm trong Collection của Kotlin. Trong bày này chúng ta sẽ tiếp tục cùng tìm hiểu các hàm được sử dụng để thao tác với dữ liệu bên trong Collection. Việc nắm được cách sử dụng của các Functions này sẽ giúp ích rất nhiều trong quá trình xây dụng ứng dụng Android nói riêng và việc sử dụng ngôn ngữ Kotlin nói chung.
1. Xoá các chuỗi (String) bị lặp trong danh sách
fun main() { val list = arrayOf("A", "B", "C", "A", "B", "E") println(list.distinct()) val list2 = arrayOf("A", "B", "C", "A", "B", "E") println(list2.toSet()) val list3 = arrayOf("A", "B", "C", "A", "B", "E") println(list3.toMutableSet()) val list4 = arrayOf("A", "B", "C", "A", "B", "E") println(list4.toHashSet()) }
Kết quả sẽ là
[A, B, C, E]
[A, B, C, E]
[A, B, C, E]
[A, B, C, E]
2. Chuyển một array hoặc list thành một chuỗi ký tự (String)
Chúng ta có thể chuyển (convert) một mảng (array) hoặc một danh sách (list) thành một chuỗi ký tự (String) bằng cách sử dụng hàm joinToString .
fun main() { val listData = listOf( "Đây", "là", "ví dụ", "nối", "các", "phần tử" ) val result = listData.joinToString( separator = ", ", //Các phần tử sẽ được nối cách nhau bởi dấu , prefix = "Xuất hiện đầu chuỗi: ", //Chuỗi ký tự sẽ xuất hiện ở đầu của chuỗi kết quả postfix = "(Xuất hiện cuối chuỗi).", //Chuỗi ký tự sẽ xuất hiện ở đuôi của chuỗi kết quả limit = listData.size - 1, //Số lượng phần tử trong danh sách sẽ được nối thành chuỗi, ở đây là các phần tử trong danh sách trừ phần tử cuối cùng. truncated = "..." //Chuỗi ký tự sẽ xuất hiện trong trường hợp ta không nối hết các phần tử của danh sách thành chuỗi ) println(result) }
Kết quả sẽ là:
Xuất hiện đầu chuỗi: Đây, là, ví dụ, nối, các, ...(Xuất hiện cuối chuỗi).
3. Biến đổi một danh sách thành một kết quả mong muốn
Giả sử ta có một danh sách các số và ta muốn lấy ra tổng của các số trong danh sách, thì ta có thể sử dụng hàm reduce.
fun main() { val listData = listOf(1, 2, 3, 4, 5, 6) val result = listData.reduce { result, item -> result + item} println(result) }
Kết quả sẽ là
21
4. Kiểm tra xem tất cả các phần tử có cùng thoả mãn một điều kiện hay không
Trong Kotlin ta có thể sử dụng hàm all để xác định xem tất cả các phần tử trong danh sách có cùng thoả mãn một điều kiện hay không. Nếu thoả mãn kết quả thu được sẽ là true và ngược lại sẽ là false.
data class Cat(val name: String, val black: Boolean, val yellow: Boolean) fun main() { val cat1 = Cat(name = "A", black = true, yellow = false) val cat2 = Cat(name = "B", black = true, yellow = true) val cat3 = Cat(name = "C", black = true, yellow = true) val cat4 = Cat(name = "D", black = true, yellow = false) val cat5 = Cat(name = "E", black = true, yellow = true) val cat6 = Cat(name = "F", black = true, yellow = false) val cats = arrayOf(cat1, cat2, cat3, cat4, cat5, cat6) val allBlackCat = cats.all { it.black } println("Tất cả ${if(allBlackCat) "đều" else "không"} là black") val allYellowCat = cats.all { it.yellow } println("Tất cả ${if(allYellowCat) "đều" else "không"} là yellow") }
Kết quả là:
Tất cả đều là black
Tất cả không là yellow
5. Tìm một phần tử thoả mãn điều kiện trong danh sách.
Chúng ta có thể tìm một phần tử trong danh sách mà thoả mãn điều kiện mà ta mong muốn bằng cách sử dụng find hoặc single.
find sẽ trả về phần tử đầu tiên trong danh sách mà thoả mãn điều kiện. Trong trường hợp không có phần tử nào thoả mãn find sẽ trả về null.
single sẽ trả về một phần tử mà thoả mãn điều kiện, nếu như không tồn tại hoặc tồn tại nhiều hơn một phần tử mà thoả mãn điều kiện thì single sẽ ném ra một ngoại lệ (Exception).
data class Student(val name: String, val age: Int) fun main() { val students = arrayOf( Student("A", 7), Student("B", 9), Student("C", 7), Student("D", 10), Student("E", 12), Student("F", 9), ) val user7yld = students.single { it.age == 10} println("Học sinh 10 tuổi: \n $user7yld") val user15yld = students.find { it.age == 15 } println("Học sinh 15 tuổi: \n $user15yld") }
Kết quả:
Học sinh 10 tuổi:
Student(name=D, age=10)
Học sinh 15 tuổi:
null
6. Tách một danh sách thành nhiều danh sách con
Trong nhiều trường hợp ta cần phải tách một danh sách các phần tử trong một mảng thành nhiều mảng con và sau đó thực hiện thao tác trên các mảng con đó. Kotlin cung cấp cho ta hàm chunked để thực hiện việc tách nhỏ mảng ra.
fun main() { val listData = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9) val chunkedLists = listData.chunked(4) println(chunkedLists) }
Kết quả là:
[[1, 2, 3, 4], [5, 6, 7, 8], [9]]
7. Sao chép các phần tử của mảng
Ta có thể sao chép các phần tử của một mảng đã được khai báo bằng việc sử dụng một trong các cách sau:
copyInto: Hàm này sẽ thay thế toàn bộ các phần tử trong mảng bằng giá trị của một mảng khác, trong trường hợp nếu số lượng phần tử trong mảng được sao chép nhỏ hơn số lượng mà ta muốn copy thì một exception sẽ được trả ra.
copyOfRange(fromIndex, toIndex): Trả về một mảng mới mà các phần tử sẽ được copy trong một khoảng mà ta mong muốn (từ vị trí bắt đầu đến vị trí kết thúc) trong mảng cần sao chép.
copyOf() hoặc copyOf(newSize) : Kết quả sẽ thu được một mảng mà cọp toàn bộ các phần tử của mảng gốc. Nếu ta truyền thêm tham số newSize vào trong hàm ta sẽ thu được mảng mới với kích thước mà ta mong muốn, trong trường hợp newSize không thoả mãn điều kiện thì toàn bộ mảng gốc sẽ được copy.
fun main() { val array1 = arrayOf(1, 2, 3, 4, 5) println("Mảng 1: ") array1.forEach { print(" $it ") } val array2 = arrayOf(10, 11, 12, 13, 14) println("\ncopyInto: ") array1.copyInto(destination = array2, destinationOffset = 1, startIndex = 0 , endIndex = 2) array2.forEach { print(" $it ") } println("\ncopyOfRange từ vị trí 1 đến 3 của mảng 1:") val array3 = array1.copyOfRange(1, 3) array3.forEach { print(" $it ")} println("\ncopyOf mảng 1:") val array4 = array1.copyOf() array4.forEach { print(" $it ") } }
Kết quả:
Mảng 1:
1 2 3 4 5
copyInto:
10 1 2 13 14
copyOfRange từ vị trí 1 đến 3 của mảng 1:
2 3
copyOf mảng 1:
1 2 3 4 5
8. Chuyển dữ liệu trong mảng thành định dạng key – value
fun main() { val playerList = listOf( Player("A", 10, 7), Player("B", 11, 10), Player("C", 10, 5), Player("D", 9, 3), Player("E", 15, 2) ) val nameToScoreMap = playerList.associateBy { it.name } println(nameToScoreMap) }
Kết quả:
{A=Player(name=A, age=10, score=7), B=Player(name=B, age=11, score=10), C=Player(name=C, age=10, score=5), D=Player(name=D, age=9, score=3), E=Player(name=E, age=15, score=2)}
Như ta thấy trong kết quả trên thì key sẽ là tên của Player còn value sẽ là toàn bộ đối tượng Player. Trong trường hợp ta chỉ muốn value sẽ là giá trị của score thì ta chỉ cần sửa lại như sau:
data class Player(val name: String, val age: Int,val score: Int) fun main() { val playerList = listOf( Player("A", 10, 7), Player("B", 11, 10), Player("C", 10, 5), Player("D", 9, 3), Player("E", 15, 2) ) val nameToScoreMap = playerList.associateBy({it.name}, {it.score}) println(nameToScoreMap) }
Kết quả:
{A=7, B=10, C=5, D=3, E=2}
9. Lọc ra một mảng chỉ chứa các phần tử tồn tại duy
Ta sử dụng hàm distinct để tạo ra một mảng mới mà chỉ chứa các phần tử duy nhất trong đó.
fun main() { val list = listOf(1, 2, 3, 3, 4, 2, 4, 5, 7, 7, 7, 7) println(list.distinct()) }
Kết quả:
[1, 2, 3, 4, 5, 7]
10. Kết hợp hai danh sách
Chúng ta sử dụng hàm union để tạo ra một danh sách mới chỉ gồm các phần tử duy nhất được lấy từ 2 danh sách thành phần. Thứ tự sắp xếp của các phần tử trong mảng mới sẽ theo thứ tự từ mảng con thứ 1 sau đó đến mảng con thứ 2.
fun main() { val list = listOf(1, 2, 3, 3, 4, 2, 4, 5, 7, 7, 7, 7) val list2 = listOf(9, 10, 2, 11, 7, 12) println(list.union(list2)) }
Kết quả:
[1, 2, 3, 4, 5, 7, 9, 10, 11, 12]
11. Lấy ra các phần tử chung của hai danh sách với intersect
fun main() { val list = listOf(1, 2, 3, 4, 5, 6, 1) val list2 = listOf(2, 2, 4, 5, 6, 7, 8) println(list.intersect(list2)) }
Kết quả:
[2, 4, 5, 6]
12. Xoá hoặc giữ các phần tử của một mảng đã tồn tại trong một mảng khác.
retainAll sẽ giữ lại tất cả các phần tử của một mảng mà các phần tử đó cũng tồn tại trên mảng khác. Nếu có phần tử bị xoá retainAll sẽ trả về true ngược lại sẽ trả về false.
fun main() { val list = mutableListOf(1, 2, 3, 3, 5) val list2 = listOf(1, 2, 3, 3, 5) val list3 = listOf(1, 2, 3, 6, 7) println("list gốc: ") println(list) println("\nkết quả list retainAll list2: ") println(list.retainAll(list2)) println("\nlist sau khi retainAll list2: ") println(list) println("kết quả list retainAll list3: ") println(list.retainAll(list3)) println("\nlist sau khi retainAll list3: ") println(list) }
Kết quả:
list gốc:
[1, 2, 3, 3, 5]
kết quả list retainAll list2:
false
list sau khi retainAll list2:
[1, 2, 3, 3, 5]
kết quả list retainAll list3:
true
list sau khi retainAll list3:
[1, 2, 3, 3]
removeAll sẽ xoá tất cả các phần tử của một mảng mà phần tử đó đã tồn tại trên mảng khác. Nếu có phần tử bị xoá removeAll sẽ trả về true ngược lại là false.
fun main() { val list = mutableListOf(1, 2, 3, 3, 5, 7) val list2 = listOf(1, 2, 3, 3, 6) val list3 = listOf(1, 2, 3, 6, 7) println("list gốc: ") println(list) println("\nkết quả list removeAll list2: ") println(list.removeAll(list2)) println("\nlist sau khi removeAll list2: ") println(list) println("kết quả list removeAll list3: ") println(list.removeAll(list3)) println("\nlist sau khi removeAll list3: ") println(list) }
Kết quả:
list gốc:
[1, 2, 3, 3, 5, 7]
kết quả list removeAll list2:
true
list sau khi removeAll list2:
[5, 7]
kết quả list removeAll list3:
true
list sau khi removeAll list3:
[5]
13. Lọc các phần tử của danh sách theo điều kiện
Chúng ta có thể sử dụng filter để lấy ra các phần tử mà thoả mãn các điều kiện mà ta mong muốn.
fun main() { val list = listOf(1, 2, 3, 4, 5, 6) //Lấy ra các phần tử chẵn trong màn list và đặt chúng vào trong mảng filteredList val filteredList = list.filter { it % 2 == 0} println(filteredList) }
Kết quả:
[2, 4, 6]
Trong trường hợp ta muốn sử dụng vị trí của các phần tử trong list để thêm vào các điều kiện lọc, ta có thể dùng filterIndexed hoặc filterIndexedTo
fun main() { val list = listOf(1, 2, 3, 4, 5, 6) //Lấy ra các phần tử chẵn từ vị trí số 2 trở đi trong màn list và đặt chúng vào trong mảng filteredList val filteredList = list.filterIndexed { index, item -> (index >= 2) && (item % 2 == 0)} println(filteredList) //Thay vì dùng filterIndexed ta cũng có thể sử dụng filterIndexedTo //Lấy ra các phần tử chẵn từ vị trí số 2 trở đi trong màn list và đặt chúng vào trong mảng filteredList val result = mutableListOf<Int>() list.filterIndexedTo(result) { index, item -> (index >= 2) && (item % 2 == 0)} println(result) }
Kết quả:
[4, 6]
[4, 6]
Ta cũng có thể sử dụng filterIsInstance để lọc ra các phần tử có cùng kiểu dữ liệu trong một mảng hỗn hợp mà nó chứa nhiều kiểu dữ liệu bên trong.
fun main() { val mixedList = listOf(1, 2, 3, "A", "B", "C", 4, "D") //Lọc ra các phần tử mà có kiểu dữ liệu là chuỗi - String val strList = mixedList.filterIsInstance<String>() println(strList) }
Kết quả:
[A, B, C, D]
14. Ghép các phần tử của 2 danh sách thành một danh sách mới chứa các dữ liệu theo cặp
Zip sẽ trả về một danh sách mới chứa các phần tử theo cặp được kết hợp từ hai danh sách con. Phần tử thứ nhất trong cặp sẽ lấy từ danh sách đầu tiên, phần tử thứ hai trong cặp sẽ lấy từ danh sách thứ 2. Độ dài của danh sách mới sẽ bằng với độ dài của danh sách con ngắn hơn.
fun main() { val listOne = listOf(1, 2, 3, 4, 5) val listTwo = listOf("a", "b", "c", "d" , "e", "f") println(listOne zip listTwo) }
Kết quả:
[(1, a), (2, b), (3, c), (4, d), (5, e)]
Ngoài zip ta còn có zipWithNext chúng ta cùng xem ví dụ sau để từ đó hiểu cách dùng của nó.
fun main() { val listOne = listOf("A", "E", "C", "B") println(listOne.zipWithNext()) }
Kết quả
[(A, E), (E, C), (C, B)]
15. Tách các cặp phần tử của một danh sách thành hai danh sách mới.
Ngược lại với zip thì ta có unzip, nó dùng để tách các cặp các phần tử của một danh sách thành hai danh sách độc lập.
fun main() { val list = listOf("A" to 1, "E" to 2, "C" to 3, "B" to 4) val (strList, intList) = list.unzip() println("List 1: $strList") println("List 2: $intList") }
Kết quả:
List 1: [A, E, C, B]
List 2: [1, 2, 3, 4]
16. Tách một mảng thành hai mảng con theo điều kiện mong muốn.
Giả sử ta có một danh sách các học sinh trong một lớp và ta muốn tách danh sách thành thành hai danh sách con, một chứa các học sinh nam, một chứa các học sinh nữ. Để thực hiện điều này dễ dàng trong Kotlin ta sử dụng hàm partition.
data class Student(val name: String, val male: Boolean) fun main() { val students = listOf ( Student("A", true), Student("B", false), Student("C", true), Student("D", false), Student("E", false), Student("F", true), ) val (maleStudents, femaleStudents) = students.partition { it.male } println("Danh sách học sinh nam") println(maleStudents) println("Danh sách học sinh nữ") println(femaleStudents) }
Kết quả:
Danh sách học sinh nam
[Student(name=A, male=true), Student(name=C, male=true), Student(name=F, male=true)]
Danh sách học sinh nữ
[Student(name=B, male=false), Student(name=D, male=false), Student(name=E, male=false)]
17. Đảo ngược vị trí của các phần tử trong danh sách.
Trong Kotlin ta có thể dùng revered và asReversed để đảo ngược một danh sách.
reversed() có thể dùng với Array, List và MutableList, sau khi thực hiện một danh sách mới sẽ được sinh ra và các phần tử trong danh sách mới này sẽ có vị trí ngược so với danh sách gốc. Các phần tử trong danh sách mới sẽ độc lập với các phần tử trong danh sách gốc, nghĩa là mọi thay đổi của các phần tử trong danh sách gốc sẽ không ảnh hưởng đến các phần tử trong danh sách mới.
asReversed() hàm này hỗ trợ List và MutableList, khác với reversed thì các giá trị của danh sách mới sẽ tham chiếu vào các giá trị của danh sách gốc. Mọi thay đổi của các phần tử trong danh sách gốc sẽ đều thay đổi tương ứng với danh sách mới.
fun main() { val list = mutableListOf(1, 2, 3) println("Danh sách gốc: $list") val newList = list.reversed() println("Danh sách mới dùng reversed: $newList") val newList2 = list.asReversed() println("Danh sách mới dùng asReversed: $newList2") list[0] = 10 println("Danh sách gốc sau khi cập nhật: $list") println("Danh sách dùng reversed trước đó: $newList") println("Danh sách dùng asReversed trước đó: $newList2") }
Kết quả:
Danh sách gốc: [1, 2, 3]
Danh sách mới dùng reversed: [3, 2, 1]
Danh sách mới dùng asReversed: [3, 2, 1]
Danh sách gốc sau khi cập nhật: [10, 2, 3]
Danh sách dùng reversed trước đó: [3, 2, 1]
Danh sách dùng asReversed trước đó: [3, 2, 10]
18. Nhóm các phần tử của một danh sách thành các danh sách con mà có phần tử cùng thoả mãn điều kiện
Giả sử ta có một danh sách tên các học sinh trong lớp bây giờ ta cần gom nhóm tên các học sinh có cùng chữ cái đầu tiên lại.
Kết quả mong muốn sẽ như thế này:
{A=[An, Anh], B=[Bình, Bắc, Bảo], H=[Hoà, Hải], P=[Phong], V=[Vân]}
Ta sử dụng groupBy để giải quyết bài toán trên như sau:
fun main() { val list = listOf( "An", "Anh", "Bình", "Bắc", "Hoà", "Hải", "Phong", "Vân", "Bảo" ) println(list.groupBy { it.first() }) }
19. Sắp xếp các phần tử trong danh sách
Sắp xếp các phần tử theo một thứ tự là công việc rất thường gặp, để hỗ trợ giải quyết vấn đề này Kotlin cung cấp cho ta hàm sorted().
fun main() { val list = listOf(1, 3, 2, 10, 7, 19, 15) println(list.sorted()) }
Kết quả:
[1, 2, 3, 7, 10, 15, 19]
Leave a Reply