Contents
Chào mừng bạn đến với Fx Studio. Chúng ta tiếp tục chuyến du lịch với ngôn ngữ Dart. Chủ đề bài viết này là List Type. Một trong những kiểu dữ liệu Collections trong Dart. Bên cạnh đó, chúng ta sẽ tìm hiểu các vấn đề liên quan & các toán tử dùng với List.
Nếu mọi việc đã ổn rồi, thì …
Bắt đầu thôi!
Chuẩn bị
Về mặt công cụ editor thì khá đơn giản:
- TextEditor
- Visual Studio Code (nên dùng)
Hoặc bạn vào trang https://dartpad.dev/ để tiến hành code luôn. Khá là giống với Playground của Swift.
Vè mặt lý thuyết, nếu bạn chưa biết gì về Dart, thì có thể theo dõi lại các bài viết trong series Dart Tour nhóe.
List type
List hay còn gọi là Array theo cái tên dân gian lập trình thường dùng.
Đây là một kiểu dữ liệu phổ biến nhất trong Dart cũng như trong các ngôn ngữ lập trình khác.
Nó có những đặc điểm cơ bản sau:
- Là một cấu trúc dữ liệu để sắp xếp thứ tự các đối tượng.
- Các đối tượng trong List thì có cùng kiểu dữ liệu với nhau
- Phần tử đầu tiên sẽ có
index = 0
- Thứ tự các phần tử trong một danh sách rất quan trọng.
Như vậy chắc cũng ổn rồi, bắt tay vào việc chính thôi.
Create List
List type sẽ được tạo bằng việc khai báo các đối tượng cùng loại trong cặp dấu []
. Ví dụ cơ bản nhất như sau:
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
Đó là một List type với kiểu int
cho các phần tử. Chúng ta sẽ gọi ngắn là List int nhoé. Công việc tạo một List như vậy được gọi là list literal. Và bạn có thể gán lại biến bằng một list literal khác.
numbers = [];
Lúc này, numbers
của chúng ta là một List rỗng, hay không chứa bất cứ phần tử nào hết.
Tuy là rỗng nhưng nó khác
null
nhoé, vì nó tồn tại.
Khai báo một List ban đầu bằng cách gán một danh sách rỗng cho nó.
var names = [];
Tuy nhiên, Dart sẽ không biết được kiểu dữ liệu chính xác cho danh sách của bạn. Nó có thể nhận nhiều kiểu dữ liệu khác nhau. Và Dart sẽ cho nó là kiểu dynamic
.
Đây không phải là một cách khuyến khích cho bạn để khai báo List trong Dart.
Syntax
Do đó, cú pháp khai báo một danh sách sẽ như sau:
// #1
List<type> list_name = [];
// #2
var list_name = <type>[];
Trong đó:
- Cách 1 là bạn sẽ xác định kiểu của List trước tiên. Sau đó là tên của List. Cuối cùng là gán với một danh sách rỗng.
- Cách 2 là bạn tạo ra một biến. Sau đó là gán bằng việc khởi tạo một List với kiểu dữ liệu xác định
Cặp dấu <>
được gọi là generic types. Bạn sẽ nhét một kiểu dữ liệu vào trong đó.
Đôi khi bạn muốn xem thử danh sách chúng ta có những gì trong đó. Bạn hãy dùng tới lệnh print
thôi.
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
print(numbers);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
Đơn giản phải không nào.
Elements of a list
Thao tác với các phần tử trong List, thì cũng tương tự việc thao tác với các kiểu Array trong các ngôn ngữ khác. Ta lấy ví dụ là một List int như sau. Và chúng ta sẽ có một số tương tác với các phần tử trong đó.
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9];
- Truy cập vào phần tử thứ
i
trong List
final second = numbers[1]; print(second); // 2
Bạn sử dụng dấu []
và điền thứ tự phần tử vào là truy cập được tới phần tử đó.
- Lấy
index
của một phần tử
final index = numbers.indexOf(9); print(index); //8 final index2 = numbers.indexOf(0); print(index2); //-1
Bạn sử dụng phương thức .indexOf()
để tìm index
của một phần tử nào đó trong List. Nó sẽ trả về index
đầu tiên được tìm thấy, bỏ qua các index
khác. Nếu không tìm thấy sẽ là -1
.
- Gán giá trị vào phần tử thứ
i
numbers[2] = 2; print(numbers); //[1, 2, 2, 4, 5, 6, 7, 8, 9, 9, 9]
Vẫn sử dụng việc truy cập vào phần tử thứ i
, nhưng chúng ta đặt ở bên phải dấu =
. Gán giá trị mới cho nó. Như vậy là ổn.
- Thêm một phần tử vào List
numbers.add(10); print(numbers); //[1, 2, 2, 4, 5, 6, 7, 8, 9, 9, 9, 10]
Dùng phương thức .add()
để thêm một phần tử mới vào danh sách.
- Xoá một phần tử trong List
numbers.remove(5); print(numbers); // [1, 2, 2, 4, 6, 7, 8, 9, 9, 9, 10] numbers.remove(2); print(numbers); // [1, 2, 4, 6, 7, 8, 9, 9, 9, 10]
Ta dùng phương thức .remove()
để xoá đi một phần tử trong danh sách.
Mutable & Immutable List
Ví dụ
Đầu tiên, chúng ta hãy xem một ví dụ sau:
var books = ['iOS', 'Android', 'Flutter', 'Kotlin', 'Swift', 'Dart']; books.add('C#'); books.remove('Android'); print(books); final names = ['Tèo', 'Tí', 'Na', 'Lam', 'Hồng', 'Dần']; names.add("Tỵ"); names.remove('Na'); print(names);
Bạn có thấy điều gì không ổn trong ví dụ trên không?
var
là biến số. Nên giá trị có thể thay đổi được. Nhưng màfinal
lại là hằng số, tại sao giá trị vẫn có thể thay đổi được.
Ta tiếp tục xem ví dụ tiếp theo nhoé!
books = ['PHP', 'HTML', 'CSS', 'JS']; print(books); names = ['Dũng', 'Đài', 'Hải', 'Cường']; //error print(names);
May quá, chúng ta đã có lỗi xãy ra với final
List rồi. Còn var
List vẫn bình an vô sự.
Giải thích
- Với
var
hayfinal
List thì sẽ không liên quan tới tới việc một danh sách có thể thay đổi được (mutable) hay không thay đổi được (immutable) - Chúng sẽ liên quan tới địa chỉ vùng nhớ. Tức là con trỏ.
var
List thì mọi chuyện khá là đơn giản. Khi nó là biến. Nó có quyền:- Thay đổi sang vùng nhớ khác (ví dụ 2)
- Thay đổi nội dung của nó (ví dụ 1)
final
List thì mọi chuyện sẽ phúc tạp hơn. Khi con trỏ sẽ trỏ tới vùng nhớ lúc được cấp phát lần đầu tiên. Nó sẽ:- Không chuyển sang vùng nhớ khác hay gán con trỏ khác cho nó (ví dụ 2)
- Nhưng nó có thể thay đổi nội dung liên quan tới vùng nhớ mà nó trỏ vào (ví dụ 1)
Thật là mệt mỏi. Đúng là trong hư có thật mà trong thật có hư.
Deeply immutable lists
Và giờ bạn quyết tâm tạo một danh sách mà bất khả xâm phạm. Dù thay đổi vùng nhớ hay là thay đổi nội dung đi cho nữa, thì đều không được hết. Cách giải quyết khá là đơn giản, thay bằng từ khoá const
là xong.
Ví dụ như sau:
const names = ['Tèo', 'Tí', 'Na', 'Lam', 'Hồng', 'Dần']; // or final names = const ['Tèo', 'Tí', 'Na', 'Lam', 'Hồng', 'Dần'];
Nhìn hơn phèn một chút, nhưng bạn sẽ an tâm là cho dù gán hay add
hay remove
đều không thể làm được.
Tuy nhiên, nhiều bạn cố chấp vẫn muốn tạo một danh sách là final
vì giá trị phải được tính toán lúc run-time. Nhưng lại muốn nó là immutable. Dart sẽ cho chúng ta một giải pháp, đó là List.unmodifiable()
. Ví dụ:
final modifiableList = [DateTime.now(), DateTime.now()]; final unmodifiableList = List.unmodifiable(modifiableList);
Bạn sẽ có danh sách unmodifiableList
được tạo ra từ modifiableList
lúc run-time. Và nó sẽ không bị thay đổi được.
Bạn hài lòng với từ khoá
final
rồi chứ.
List Properties
Ta tìm hiểu các thuộc tính cơ bản của một List type qua các ví dụ sau. Giả sử bạn có List như thế này.
const drinks = ['water', 'milk', 'juice', 'soda'];
- First & Last elements
drinks.first // water drinks.last // soda
Với .first
& .last
là bạn nhanh chóng truy cập vào phần tử đầu tiên và cuối cùng của một danh sách.
- Checking if a list contains any elements
Kiểm tra xem thử danh sách chúng ta có phần tử hay không có phần tử nào cả, bằng 2 thuộc tính sau:
drinks.isEmpty // false drinks.isNotEmpty // true
- Length
Sử dụng thuộc tính .length
để xem có bao nhiêu phần tử trong một danh sách.
drinks.length == 0 // false drinks.length > 0 // true
- Loop
Nôm na thì bạn sẽ có 2 cách duyệt từng phần tử trong một List. Đó là for
và forEach
. Xem ví dụ nhoé.
// for in for (var item in drinks) { print(item); } // forEach desserts.forEach((dessert) => print(dessert)); desserts.forEach(print);
Với cách cuối được gọi là tear-off
, bạn sẽ lượt bỏ qua những cú pháp không cần thiết.
Exten for Flutter
Bây giờ chúng ta lại sang phần crossover giữa Dart & Flutter. Vì chúng nó có sự ảnh hưởng qua lại lẫn nhau. Nên sẽ có một số toán tử được thêm vào như sau:
Spread operator
Để bắt đầu, bạn xem qua ví dụ sau nhoé!
const list1 = ["1", "2", "3", "4", "5"]; const list2 = ["A", "B", "C", "D", "E"]; const list3 = ["0", ...list1, "&", ...list2, "F"]; print(list3); //[0, 1, 2, 3, 4, 5, &, A, B, C, D, E, F]
Bạn cũng đủ đoán ra ý nghĩa của toán tử ...
rồi chứ. Nó được gọi là spread operator. Giúp bạn tạo một danh sách mới bằng việc thêm một danh sách khác vào trong nó.
Ngoài ra, áp dụng với List là nullable, ta sẽ có toán tử null spread operator (...?)
. Bạn xem ví dụ nhoé.
List<String>? coffees; final hotDrinks = ['milk tea', ...?coffees]; print(hotDrinks);
Bạn có một danh sách mới, tạo từ việc mở rộng 1 danh sách cộng thêm một List nullable. Nếu như ví dụ, nó không có ý nghĩa mấy. Chắc chúng ta sẽ tìm hiểu sau.
Collection if
Một toán tử mới, à mà đúng ra là 1 cách dùng mới khá là bá đạo. Khi bạn có thể thêm 1 câu lệnh điều kiện if
vào trong 1 List, để quyết định rằng có nên thêm vào 1 phần tử tiếp theo hay không.
Xem ví dụ là hiểu liền nhoé!
const isOkay = false; const list4 = ['A', 'B', if (isOkay) 'C', 'D']; print(list4); //[A, B, D]
Trong đó,
- Bạn chú ý tới các
const
dùng để khai báo là các hằng số và không thay đổi được - Tuy nhiên
list4
có số lượng các phần tử phụ thuộc vàoisOkay
- Cụ thể là việc quyết định có thêm
C
vào trong List hay không tuỳ thuộc vào điều kiệnif
kia
Bạn hãy thử thay đổi giá trị isOkay = true
, và cảm nhận kết quả nhoé.
Collection for
Và bạn nghĩ thử xem là tụi Dart có dám cho for
và trong 1 List nữa hay không. Xem ví dụ code sau nhoé:
const list5 = ['1', '2', '3', '4', '5']; var list6 = ['0', for (var item in list5) item, '6', '7']; print(list6);
Trong đó
- Phải sử dụng
var
cho khai báo danh sách cuối cùng rồi. list6
được tạo nên bởi việc lặp các phần tửlist5
và trong bản thân danh sách gán cho nó.
Một nước đi mà chúng ta không ngờ được.
Tạm kết
- Tìm hiểu về List Type trong Dart
- Cấu tạo & cú pháp cho việc khai báo một List
- Các toán tử & thuộc tính cơ bản của List
- Mở rộng List trong Flutter
Okay! Tới đây, mình xin kết thúc bài viết về List type trong series Dart Tour. Nếu có gì thắc mắc hay góp ý cho mình thì bạn có thể để lại bình luận hoặc gởi email theo trang Contact.
Cảm ơn bạn đã đọc bài viết này!
Related Posts:
Written by chuotfx
Hãy ngồi xuống, uống miếng bánh và ăn miếng trà. Chúng ta cùng nhau đàm đạo về đời, về code nhóe!
Leave a Reply Cancel reply
Fan page
Tags
Recent Posts
- Complete Concurrency với Swift 6
- 300 Bài code thiếu nhi bằng Python – Ebook
- Builder Pattern trong 10 phút
- Observer Pattern trong 10 phút
- Memento Pattern trong 10 phút
- Strategy Pattern trong 10 phút
- Automatic Reference Counting (ARC) trong 10 phút
- Autoresizing Masks trong 10 phút
- Regular Expression (Regex) trong Swift
- Lập trình hướng giao thức (POP) với Swift
You may also like:
Archives
- July 2024 (1)
- June 2024 (1)
- May 2024 (4)
- April 2024 (2)
- March 2024 (5)
- January 2024 (4)
- February 2023 (1)
- January 2023 (2)
- November 2022 (2)
- October 2022 (1)
- September 2022 (5)
- August 2022 (6)
- July 2022 (7)
- June 2022 (8)
- May 2022 (5)
- April 2022 (1)
- March 2022 (3)
- February 2022 (5)
- January 2022 (4)
- December 2021 (6)
- November 2021 (8)
- October 2021 (8)
- September 2021 (8)
- August 2021 (8)
- July 2021 (9)
- June 2021 (8)
- May 2021 (7)
- April 2021 (11)
- March 2021 (12)
- February 2021 (3)
- January 2021 (3)
- December 2020 (3)
- November 2020 (9)
- October 2020 (7)
- September 2020 (17)
- August 2020 (1)
- July 2020 (3)
- June 2020 (1)
- May 2020 (2)
- April 2020 (3)
- March 2020 (20)
- February 2020 (5)
- January 2020 (2)
- December 2019 (12)
- November 2019 (12)
- October 2019 (19)
- September 2019 (17)
- August 2019 (10)