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
List
gồ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
n
phầ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àindex
chỉ 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óavar
hoặ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
List
có 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ớiindex
là 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
var
vì 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
List
trong 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
List
có độ 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ố
index
củaList
ta 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ộtList
và trả vềList
mớ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íindex
xá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ụci
tới vị tríj-1
bở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àtrue
nế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íindex
và 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ụci
tớ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