Lấy lại giá trị từ điển Các phương pháp hay nhất


79

Gần đây tôi mới nhận thấy Dictionary.TryGetValue(TKey key, out TValue value)và tò mò về cách tiếp cận tốt hơn để truy xuất một giá trị từ Từ điển.

Theo truyền thống, tôi đã làm:

if (myDict.Contains(someKey))
     someVal = myDict[someKey];
     ...

trừ khi tôi biết nó được trong đó.

Tốt hơn là chỉ cần làm:

if (myDict.TryGetValue(somekey, out someVal)
    ...

Cách thực hành nào tốt hơn? Cái này có nhanh hơn cái kia không? Tôi sẽ tưởng tượng rằng phiên bản Thử sẽ chậm hơn khi nó 'nuốt' một thử / bắt vào bên trong chính nó và sử dụng điều đó như logic, phải không?

Câu trả lời:


84

TryGetValue nhanh hơn một chút, vì FindEntry sẽ chỉ được gọi một lần.

Nhanh hơn bao nhiêu? Nó phụ thuộc vào tập dữ liệu trong tay. Khi bạn gọi phương thức Chứa, Từ điển thực hiện tìm kiếm nội bộ để tìm chỉ mục của nó. Nếu nó trả về true, bạn cần tìm kiếm chỉ mục khác để lấy giá trị thực. Khi bạn sử dụng TryGetValue, nó chỉ tìm kiếm chỉ mục một lần và nếu được tìm thấy, nó sẽ gán giá trị cho biến của bạn.

FYI: Nó không thực sự bắt lỗi.

Nó đang gọi:

public bool TryGetValue(TKey key, out TValue value)
{
    int index = this.FindEntry(key);
    if (index >= 0)
    {
        value = this.entries[index].value;
        return true;
    }
    value = default(TValue);
    return false;
}

ContainsKey là đây:

public bool ContainsKey(TKey key)
{
    return (this.FindEntry(key) >= 0);
}

TryGetValue nhanh hơn một chút, vì FindEntry sẽ chỉ được gọi một lần.
Joe

1
TryGetValue là nhanh hơn nhiều khi bạn có một từ điển lớn
Diadistis

4
Về mặt lý thuyết (tốt, cả trong thực tế), điều này không phụ thuộc vào kích thước của từ điển, vì thời gian truy xuất dự kiến ​​(!) Là không đổi, tức là không phụ thuộc vào kích thước từ điển!
Konrad Rudolph

29

Thực tế thì TryGetValue nhanh hơn. Nhanh hơn bao nhiêu? Nó phụ thuộc vào tập dữ liệu trong tay. Khi bạn gọi phương thức Chứa, Từ điển thực hiện tìm kiếm nội bộ để tìm chỉ mục của nó. Nếu nó trả về true, bạn cần tìm kiếm chỉ mục khác để lấy giá trị thực. Khi bạn sử dụng TryGetValue, nó chỉ tìm kiếm chỉ mục một lần và nếu được tìm thấy, nó sẽ gán giá trị cho biến của bạn.

Biên tập:

Được rồi, tôi hiểu sự nhầm lẫn của bạn nên hãy để tôi giải thích thêm:

Trường hợp 1:

if (myDict.Contains(someKey))
     someVal = myDict[someKey];

Trong trường hợp này, có 2 cuộc gọi tới FindEntry, một để kiểm tra xem khóa có tồn tại hay không và một để truy xuất nó

Trường hợp 2:

myDict.TryGetValue(somekey, out someVal)

Trong trường hợp này, chỉ có một lệnh gọi đến FindKey vì chỉ mục kết quả được giữ cho truy xuất thực tế trong cùng một phương thức.


Đã đồng ý. TryGetValue loại bỏ sự cần thiết phải thực hiện tra cứu khóa hai lần. Nó cũng có thể hữu ích trong trường hợp đa luồng. Kể từ thời điểm bạn kiểm tra nếu giá trị tồn tại, nó có thể đã được thêm hoặc bớt. Điều này có thể gây ra ngoại lệ "khóa đã tồn tại" hoặc "không tìm thấy khóa".
Brian Rudolph

0

Tôi tưởng tượng rằng trygetvalue đang làm một cái gì đó giống như:

if(myDict.ReallyOptimisedVersionofContains(someKey))
{ 
  someVal = myDict[someKey];
  return true;
}
return false;

Vì vậy, hy vọng không có thử / bắt ở bất cứ đâu.

Tôi nghĩ rằng nó chỉ là một phương pháp thuận tiện thực sự. Tôi thường sử dụng nó vì nó lưu một hoặc hai dòng mã.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.