This article is currently in the process of being translated into Vietnamese (~99% done).
Dictionaries
Dictionary trong C# thực hiện IDictionary interface. Có nhiều loại Dictionary nhưng loại hay được dùng nhất là Dictionary generic, có dạng Dictionary <TKey, TValue> - nó chứa key có kiểu dữ liệu riêng biệt và giá trị có kiểu dữ liệu riêng. Đây là đặc điểm phân biệt Dictionary với List - thành phần của một list có thứ tự và có thể truy nhập bằng chỉ mục index, trong khi các phần tử trong Dictionary lại được lưu với key riêng biệt và dùng để truy nhập vào các phần tử.
Chúng ta sẽ đào sâu hơn vào dictionary, hãy xem ví dụ đơn giản sau để cho bạn biết nó như thế nào:
Dictionary<string, int> users = new Dictionary<string, int>();
users.Add("John Doe", 42);
users.Add("Jane Doe", 38);
users.Add("Joe Doe", 12);
users.Add("Jenna Doe", 12);
Console.WriteLine("John Doe is " + users["John Doe"] + " years old");
Gặp gia đình Doe, lại là ví dụ để kiểm tra trong bài này. Mẹ, bố và hai anh em sinh đôi Joe và Jenna. Chú ý cách tôi định nghĩa Dictionary để dùng chuỗi như là key (trong trường hợp này là tên) và một số nguyên là giá trị (trong trường hợp này là tuổi). Điều thú vị là nó cho phép chúng ta truy nhập vào một thành phần của dictionary dùng key thay vì index. Bạn có thể thấy rằng trong dòng cuối của ví dụ - giữa dấu ngoặc vuông chúng ta chỉ cần đưa key vào để truy nhập vào giá trị.
Có hai điều quan trọng ở đây: Đầu tiên, toàn bộ khóa phải là duy nhất. Trong trường hợp này, chúng ta dùng chuỗi là khóa, nó có nghĩa bạn không thể thêm vào hai người dùng với cùng một tên. Điều này rất logic vì khi bạn có thể dùng khóa để xác định duy nhất một phần tử, khóa chỉ có thể chỉ tới một giá trị. Hay nói cách khác, điều này làm ví dụ đơn giản hơn vì rõ ràng bạn không thể có một tập các người dùng trùng tên.
Một điều khác bạn phải nhớ là khi tru nhập vào giá trị từ một từ điển thì khóa phải tồn tại trong tập hợp, khi bạn thử truy cập vào giá trị của nó. Hay nói cách khác, ví dụ của tôi chỉ an toàn vì tôi có thể hoàn toàn điều khiển những gì mà danh sách chứa bên trong - trong tất cả các trường hợp, bạn nên kiểm tra khóa có tồn tại không trước khi dùng nó - như sau:
string key = "John Doe";
if(users.ContainsKey(key))
Console.WriteLine("John Doe is " + users[key] + " years old");
Nếu bạn cố thêm vào một khóa đã tồn tại hay bạn cố gắng truy cập vào một giá trị có khóa không tồn tại thì .NET sẽ có lỗi ngoại lệ. Nó có thể rõ ràng nhưng cả hai thường thấy trong bản ghi ngoại lệ.
Working with the items
Truy nhập vào một phần tử có thể rất hữu ích, nhưng nếu bạn muốn lặp thông qua các tập hợp ví dụ để tìm kiếm gì đó thì sao? Trong trường hợp đó, điều đầu tiên mà bạn phải lưu ý là các phần tử trong danh sách không chỉ là các đối tượng đơn giản - thay vì đó, Dictionary chứa các phần tử có kiểu KeyValuePair<TKey, TValue>. T là kiểu dữ liệu bạn dùng để khai báo danh sách - trong trường hợp này là một chuỗi hay một số nguyên. Do đó lặp thông qua vòng lặp foreach như sau:
Dictionary<string, int> users = new Dictionary<string, int>()
{
{ "John Doe", 42 },
{ "Jane Doe", 38 },
{ "Joe Doe", 12 },
{ "Jenna Doe", 12 }
};
foreach (KeyValuePair<string, int> user in users)
{
Console.WriteLine(user.Key + " is " + user.Value + " years old");
}
Điều đầu tiên mà bạn để ý là thay đổi cách khởi tạo dictionary - thay vì thêm từng phần tử thì tôi dùng cú pháp initializer, như đã mô tả trong bài trước đây.
Chúng ta có một dictionary giống hệt trước - hãy dùng vòng lặp. Như bạn thấy tôi dùng vòng foreach và tôi khai báo là kiểu KeyValuePair<string, int> - chính xác về kiểu dữ liệu của khóa và giá trị trong dictionary. Bây giờ chúng ta có thể truy nhập vào cả khóa và giá trị (tên và tuổi) của mỗi phần tử và chúng ta dùng để hiển thị một chuỗi thông tin đơn giản về người trong Console.
The order of items
Ví dụ trên cung cấp cho chúng ta một điều quan trọng: Không giống Danh sách, nơi mà thứ tự của các phần tử được lưu trong chỉ mục số, thứ tự các phần tử trong dictionary là không xác định - bạn chỉ đơn giản dựa trên các phần tử ở một thứ tự nhất định, thậm chí cả khi bạn thêm các phần tử lần lượt. Chắc chắn rằng, khi bạn chạy ví dụ trên, bạn có thể thấy các phần tử ở cùng thứ tự khi chúng ta thêm nó nhưng không có gì đảm bảo, và ngay khi bạn có dictionary với nhiều phần tử và bắt đầu thêm và loại bỏ chúng thì thứ tự có thể thay đổi.
Không dùng phương thức Sort() cho dictionary vì cuối cùng nếu bạn dùng thì thứ tự có thể thay đổi ngay khi bạn bắt đầu làm việc lại với nó. Thay vì đó, bạn có thể dùng OrderBy() và OrderByDescending() từ LINQ (nói về nó trong chương khác) để có một bản sao của Dictionary. Nó cũng cho phép bạn sắp xếp theo khóa hay theo giá trị, rất hữu ích trong ví dụ để sắp xếp người dùng theo tuổi của họ:
Dictionary<string, int> users = new Dictionary<string, int>()
{
{ "John Doe", 42 },
{ "Jane Doe", 38 },
{ "Joe Doe", 12 },
{ "Jenna Doe", 12 }
};
foreach (KeyValuePair<string, int> user in users.OrderBy(user => user.Value))
{
Console.WriteLine(user.Key + " is " + user.Value + " years old");
}
Nếu bạn chạy dữ liệu, bạn sẽ thấy thậm chí khai báo dictionary với các phần tử theo một thứ tự thì chúng ta vẫn có thể dễ dàng sắp xếp theo thứ tự khác. Chỉ cần nhớ rằng bạn đảm bảo bạn có các phần tử theo thứ tự bạn muốn.