Kiểu danh sách List trong Dart
Kiểu dữ liệu danh sách List trong Dart được sử dụng để biểu diễn cho một tập hợp các đối tượng theo một thứ tự nhất định. Kiểu danh sách List trong Dart tương đương với kiểu mảng Array trong các ngôn ngữ khác (Python chẳng hạn).
Một List là một nhóm có thứ tự các đối tượng. Một List sử dụng để chứa nhiều đối tượng / giá trị – ta gọi chung là phần tử – trong một biến duy nhất.
1. Khai báo một danh sách List trong Python
- Một
Listgồm các phần tử được phân tách bằng dấu phẩy,và được đặt trong dấu ngoặc vuông[]. - Một danh sách gồm
nphần tử thì các phần tử được đánh số thứ tự từ0đếnn-1. Số thứ tự của mỗi một phần tử được gọi làindexchỉ mục của phần tử đó. Kích thước (độ dài) của một danh sách có thể biết được bằng cách sử dụng phương thứclength - Khai báo một danh sách
List, chúng ta có thể sử dụng từ khóavarhoặc khai báo kiểu các phần tử củaList.
var tenDS = [các phần tử];
hoặc
List<kieu_phan_tu> tenDS = [các phần tử];
- Ví dụ sau, chúng ta khai báo một
Listcó tên làmonAnđể lưu trữ 4 phần tử thuộc kiểu String là'cơm','canh','cà'và'cá'.
var monAn = ['cơm', 'canh', 'cà', 'cá']; List<String> hoaQua = ['nho', 'táo', 'cam', 'bưởi', 'sầu riêng']; monAn.length; //kết quả 4 hoaQua.length; //kết quả 5
- Để truy cập đến một phần tử của List
danh_sách, chúng ta dùng cú phápdanh_sách[index]vớiindexlà chỉ mục của phần tử đó trongdanh_sách. Ví dụ với ListmonAnở trên, thì phần tử có index 1 là'canh'
monAn[1]; //kết quả 'canh' hoaQua[0]; //kết quả 'nho'
- Để truy cập đến nhiều phần tử liên tiếp nhau của List, chúng ta dùng cú pháp
tenDanhSach.sublist(i,j)
trong đó i là chỉ số của phần tử đầu tiên, j là chỉ số của phần tử cuối cùng cần lấy ra tính từ đầu List. Nếu muốn lấy từ phần tử từ chỉ số i đến cuối danh sách, chúng ta dùng tenDanhSach.sublist(i,)
- Tuy nhiên, chúng ta ưu tiên cách khai báo sử dụng từ khóa
varvì tính ngắn gọn của nó.
2. Các loại danh sách List trong Dart
Trong Dart, danh sách List có thể được phân loại thành:
- Danh sách độ dài cố định
- Danh sách có thể mở rộng
Danh sách độ dài cố định (Fixed Length List)
- Một đối tượng
Listtrong Dart có thể được khai báo với kích thước cố định, không thể thay đổi bằng cú pháp:
var list_name = List(size);
- Sau đó, để gán giá trị cho từng phần tử của danh sách, chúng ta dùng toán tử gán
=cho từng phần tử của danh sách.
Chú ý rằng, từ phiên bản 2.0, với null safety thì việc tạo danh sách có kích thước cố định mà không có giá trị khởi tạo sẽ bị báo lỗi. Lúc này chúng ta phải sử dụng phương thức filled(size, default) hoặc generate(size, (i) => default) để tạo một List có kích thước size và các phần tử có giá trị mặc định default
void main() {
var trangMieng = List.filled(4,'');
trangMieng[0] = 'táo';
trangMieng[1] = 'ổi';
trangMieng[2] = 'xoài';
trangMieng[3] = 'mít';
}
Danh sách có thể mở rộng (Growable List)
- Một danh sách được khai báo không có kích thước/độ dài cụ thể được gọi là Danh sách có thể phát triển (Growable List). Độ dài của danh sách có thể phát triển có thể thay đổi trong thời gian chạy.
- Cách khai báo một
Listcó độ dài có thể phát triển như ở phần 1.
var soTuNhien = [0, 1, 2, 3, 4];
List<int> soPi = [3, 1, 4, 1, 5, 9, 2];
- Khi đó, để thay đổi các phần tử có chỉ số
indexcủaListta sử dụng phép gán thông thường. - Để thêm một phần tử mới vào List, cập nhật một phần tử hoặc xóa một phần tử, xin mời xem phần 4 dưới đây.
3. Các thuộc tính của kiểu List trong Dart
Dưới đây là danh sách các thuộc tính được hỗ trợ bởi Dart List.
| Thuộc tính | Ý nghĩa |
|---|---|
first |
Trả về phần tử đầu tiên của List. |
isEmpty |
Trả về true nếu List là rỗng (không có phần tử nào). |
isNotEmpty |
Trả về true nếu List có ít nhất một phần tử. |
length |
Trả về độ dài / kích thước của List, đây chính là số phần tử trong List. |
last |
Trả về phần tử cuối cùng trong List. |
contains(phần_tử) |
Kiểm tra xem List có chứa phần_tử hay không. |
reversed |
Trả về một Iterable chứa các phần tử của List ban đầu nhưng theo thứ tự ngược lại. |
Single |
Được sử dụng để kiểm tra xem danh sách có phải chỉ có một phần tử không và trả về phần tử đó. |
Ví dụ.
void main() {
var khaiVi = ['súp', 'gỏi tôm', 'sò huyết', 'sườn', 'thịt nguội' ];
print(khaiVi.first); //súp
print(khaiVi.last); //thịt nguội
print(khaiVi.isEmpty); //false
print(khaiVi.reversed); //(thịt nguội, sườn, sò huyết, gỏi tôm, súp)
}
4. Các phương thức của kiểu danh sách List trong Dart
4.1. Chèn các phần tử vào danh sách
add()Hàmadd(phần_tử)được sử dụng để nối thêm mộtphần_tửvào cuối mộtListvà trả vềListmới này.
void main() {
var evenList = [2,4,6,8];
print(evenList);
evenList.add(10);
print(evenList);
}
addAll()HàmaddAll(các_phần_tử)được sử dụng để thêm nhiều phần tử vào mộtList,các_phần_tửđược phân tách bằng dấu phẩy và được đặt trong dấu ngoặc vuông[]. Bạn hình dung hàm addAll() chính là nối thêm một danh sách khác vào danh sách đang có.
void main() {
var evenList = [2,4];
print(evenList);
evenList.addAll([6,8,10]);
print(evenList);
}
insert()Hàminsert(index, phần_tử)dùng để chèn thêm mộtphần_tửtử vào vị tríindexxác định.
void main() {
List danhSach = [2, 3, 4];
print(danhSach);
danhSach.insert(0, 1);
print(danhSach);
}
-
insertAll():HàminsertAll(index, các_phần_tử)được sử dụng để chèn một danh sáchcác_phần_tửvào một danh sách đã cho bắt đầu từ vị tríindex. Danh sáchcác_phần_tửđược phân tách bằng dấu phẩy được đặt trong dấu ngoặc vuông[]
void main() {
var evenList = [2, 10];
print(evenList);
evenList.insertAll(1, [4, 6, 8]);
print(evenList);
}
4.2. Cập nhật danh sách
- Cách đơn giản nhất một phần tử danh sách có thể được sửa đổi bằng cách truy cập phần tử và gán giá trị mới cho phần tử đó.
tenDanhSach[index] = giá_trị_mới;
void main() {
var evenList = [2, 4, 5, 8, 10];
print("Danh sách trước khi cập nhật ${evenList}");
evenList[2] = 6;
print("Danh sách sau khi cập nhật ${evenList}");
}
replaceRange()HàmreplaceRange(i,j,các_giá_trị_mới)được sử dụng để cập nhật một loạt các phần tử của danh sách từ vị trí chỉ mụcitới vị tríj-1bởicác_giá_trị_mới.
void main() {
var evenList = [2, 4, 5, 8, 10];
print("Danh sách trước khi cập nhật ${evenList}");
evenList.replaceRange(0,3,[2,4,6]);
print("Danh sách sau khi cập nhật ${evenList}"); //kết quả [2,4,6,8,10]
}
4.3. Xóa các phần tử danh sách
remove()Hàmremove(phần_tử)dùng để xóa mộtphần_tửxuất hiện đầu tiên tính từ đầu danh sách khỏi danh sách đó. Kết quả trả về làtruenếuphần_tửbị xóa khỏi danh sách.
void main() {
var evenList = [2, 4, 6, 8, 10, 6, 12];
print("Danh sách trước khi xóa ${evenList}");
evenList.remove(6);
print("Danh sách sau khi xóa ${evenList}"); //[2, 4, 8, 10, 6, 12]
}
removeAt()HàmremoveAt(index)được sử dụng để xóa một phần tử tại vị tríindexvà trả về phần tử tại vị tríindexđó.
void main() {
var evenList = [2, 4, 6, 8, 10, 6, 12];
print("Danh sách trước khi xóa ${evenList}");
print(evenList.removeAt(2));//trả về 6
print("Danh sách sau khi xóa ${evenList}"); //[2, 4, 8, 10, 6, 12]
}
removeLast()HàmremoveLast()được sử dụng để xóa bỏ và trả về phần tử cuối cùng của danh sách đã cho.
void main() {
var evenList = [2, 4, 6, 8, 10, 6, 12];
print("Danh sách trước khi xóa ${evenList}");
print(evenList.removeLast());//trả về 12
print("Danh sách sau khi xóa ${evenList}"); //[2, 4, 6, 8, 10, 6]
}
removeRange()HàmremoveRange(i,j)được sử dụng để xóa bỏ các phần tử từ phạm vi chỉ mụcitới trướcj(tức là từiđếnj-1).
void main() {
var evenList = [2, 4, 6, 8, 10, 6, 12];
print("Danh sách trước khi xóa ${evenList}");
evenList.removeRange(2,3);
print("Danh sách sau khi xóa ${evenList}"); //[2, 4, 8, 10, 6, 12]
}
5. Các phương thức nâng cao của List
5.1. Duyệt các phần tử của List trong Dart
Trong Dart, chúng ta có thể duyệt tuần tự qua các phần tử danh sách bằng phương thức forEach như sau:
void main() {
var list = ["Xuân", "Hạ", "Thu", "Đông"];
list.forEach((item) {
print('$item');
});
}
5.2. Sắp xếp các phần tử trong List
Sử dụng phương thức sort. Bạn có thể đọc thêm về hàm này tại đây https://api.dart.dev/stable/2.12.2/dart-core/dart-core-library.html
void main() {
var khaiVi = ['súp', 'gỏi tôm', 'sò huyết', 'sườn', 'thịt nguội' ];
khaiVi.sort();
print(khaiVi);//[gỏi tôm, sò huyết, súp, sườn, thịt nguội]
}
5.3. Hàm map
Hàm map(f(e)) → Iterable dùng để ánh xạ mỗi phần tử e của List qua hàm f thành phần tử f(e) của một Iterable mới.
void main() {
var soChan = [0, 2, 4, 6, 8, 10];
print(soChan.map((i) => i +1)); //kết quả (1, 3, 5, 7, 9, 11)
}
5.4. Hàm every
Hàm every(bool f(E element)) sử dụng để kiểm tra xem mọi phần tử element của E có thỏa mãn hàm f hay không.
void main() {
var soChan = [0, 2, 4, 6, 8, 10];
var soLe = [1, 2, 3, 4, 5, 6, 7, 8, 9];
print(soChan.every((i) => i % 2 == 0)); //true
print(soLe.every((i) => i.isOdd)); //false
}
6. Danh sách của danh sách trong Dart
Vì Dart không hỗ trợ kiểu mảng 2 chiều nên chúng ta phải sử dụng danh sách của danh sách. Tức là mỗi phần tử của List lại là một List khác.
void main() {
var khaiVi = ['súp', 'gỏi tôm', 'sò huyết', 'sườn', 'thịt nguội' ];
var monChinh = ['tôm hùm', 'cua hoàng đế', 'nem công', 'chả phượng'];
var trangMieng = ['bánh chuối', 'chè sen', 'bánh cuộn', 'bánh nếp'];
var monAn = [khaiVi, monChinh, trangMieng];
print(monAn);
}
Khi đó, để truy cập đến một phần tử cụ thể của danh sách, chúng ta dùng cú pháp
tenDanhSach[i][j]
Ví dụ, monAn[1] sẽ trả về danh sách ['tôm hùm', 'cua hoàng đế', 'nem công', 'chả phượng'] còn monAn[1][2] sẽ trả về phần tử 'nem công'
Xem tài liệu về kiểu List đầy đủ nhất tại https://api.dart.dev/stable/2.10.5/dart-core/List-class.html
