2009-06-19 92 views
15

từ điển của tôi:Lấy phần tử cuối cùng trong từ điển?

Dictionary<double, string> dic = new Dictionary<double, string>(); 

Làm thế nào tôi có thể trở lại yếu tố cuối cùng trong từ điển của tôi không?

+0

xác định phần tử cuối cùng: được chèn lần cuối? phần tử được sắp xếp cuối cùng? –

+0

Tôi giả định chèn lần cuối. – RichardOD

+0

phần tử được chèn vào cuối cùng – subprime

Trả lời

41

Ý của bạn là gì? Bạn có nghĩa là giá trị gia tăng cuối cùng?

Lớp Dictionary<TKey,TValue> là bộ sưu tập không có thứ tự. Việc thêm và xóa các mục có thể thay đổi những gì được coi là phần tử đầu tiên và cuối cùng. Do đó không có cách nào để có được phần tử Last được thêm vào.

Có một lớp từ điển được đặt hàng có sẵn ở dạng SortedDictionary<TKey,TValue>. Nhưng điều này sẽ được sắp xếp dựa trên so sánh các khóa và không phải thứ tự mà các giá trị được thêm vào.

EDIT

Nhiều người đã đề cập bằng các cách tiếp cận phong cách LINQ sau

var last = dictionary.Values.Last(); 

Hãy cẩn trọng với về việc sử dụng phương pháp này. Nó sẽ trả về giá trị cuối cùng trong bộ sưu tập Giá trị. Đây có thể là hoặc không phải là giá trị cuối cùng bạn đã thêm vào Từ điển. Nó có lẽ là có khả năng không được như nó được.

+1

Upvote cho các cảnh báo về việc không sử dụng cách tiếp cận LINQ phong cách vì nó không trả lại những gì subprime yêu cầu. – RichardOD

+5

Mặc dù không có phiên bản chung, có một OrderedDictionary trong System.Collection.Specialized không gian tên duy trì các mục trong thứ tự chèn. – LBushkin

+1

@subprime, trong trường hợp đó sử dụng LastOrDefault thay vì Last. – JaredPar

0

Nếu bạn chỉ muốn giá trị, điều này sẽ làm việc (giả sử bạn có thể sử dụng LINQ):

dic.Values.Last() 
+0

Bạn cũng có thể sử dụng "dic.Last()" để lấy toàn bộ cặp khóa/giá trị. Họ nên làm việc giống nhau –

0

Bạn có thể sử dụng:

dic.Last() 

Nhưng một cuốn từ điển không thực sự có một cuối cùng phần tử (các cặp bên trong không được sắp xếp theo bất kỳ cách nào). Vật phẩm cuối cùng sẽ luôn giống nhau, nhưng không rõ nguyên tố nào có thể.

0

Với Net 3.5:

string lastItem = dic.Values.Last() 
string lastKey = dic.Keys.Last() 

... nhưng hãy nhớ rằng một từ điển được không ra lệnh, vì vậy bạn không thể dựa vào một thực tế rằng các giá trị sẽ vẫn theo thứ tự.

5

Nếu bạn đang sử dụng .NET 3.5, xem xét:

dic.Keys.Last() 

Nếu bạn muốn có một trật tự có thể dự đoán, tuy nhiên, sử dụng:

IDictionary<int, string> dic = new SortedDictionary<int, string>(); 
+0

Mọi cuộc gọi đến "Last()" sẽ trả lại kết quả tương tự, cho đến khi chèn hoặc thêm "Add()", đúng không? Tại thời điểm đó nó có thể có thể khác nhau? – DevinB

+0

Tôi tin như vậy, nhưng vì đó là một bộ sưu tập không có thứ tự, lần thêm cuối cùng có thể ở đâu đó ở giữa bộ sưu tập. Tôi không chắc làm thế nào nó được thực hiện trong nội bộ, hoặc những gì Last() thực sự trả về. Ai đó có nhiều kiến ​​thức về nội bộ sẽ phải trả lời điều đó. Giải phóng tín hiệu Skeet. –

18

Từ điển là bộ sưu tập có thứ tự - như vậy, có không có khái niệm về yếu tố đầu tiên hoặc cuối cùng. Nếu bạn đang tìm kiếm một lớp học hoạt động như một từ điển nhưng vẫn duy trì thứ tự chèn các mục, hãy cân nhắc sử dụng OrderedDictionary.

Nếu bạn đang tìm kiếm bộ sưu tập sắp xếp các mục, hãy cân nhắc sử dụng SortedDictionary<TKey,TValue>.

Nếu bạn có một cuốn từ điển hiện có, và bạn đang tìm kiếm các yếu tố 'cuối cùng' đưa ra một số thứ tự sắp xếp, bạn có thể sử dụng LINQ để sắp xếp bộ sưu tập, một cái gì đó như:

myDictionary.Values.OrderBy(x => x.Key).Last(); 

Bằng cách thận trọng của việc sử dụng Dictionary.Keys.Last() - trong khi danh sách khóa được sắp xếp bằng cách sử dụng mặc định IComparer cho loại khóa, giá trị bạn nhận được có thể không phải là giá trị bạn mong đợi.

+1

Con người đó gọn gàng hơn câu trả lời của tôi +1; – Hardwareguy

3

Xem xét tạo bộ sưu tập tùy chỉnh chứa tham chiếu trong phương thức Add của bộ sưu tập tùy chỉnh. Điều này sẽ đặt trường riêng tư chứa khóa/giá trị được thêm cuối cùng (hoặc cả hai) tùy thuộc vào yêu cầu của bạn.

Sau đó, có phương thức Last() trả về điều này. Dưới đây là một bằng chứng của khái niệm lớp để hiển thị những gì tôi có ý nghĩa (xin đừng gõ thiếu thực hiện giao diện etc- nó là mẫu mã):

public class LastDictionary<TKey, TValue> 
{ 
    private Dictionary<TKey, TValue> dict; 

    public LastDictionary() 
    { 
     dict = new Dictionary<TKey, TValue>(); 
    } 

    public void Add(TKey key, TValue value) 
    { 
     LastKey = key; 
     LastValue = value; 
     dict.Add(key, value); 
    } 

    public TKey LastKey 
    { 
     get; private set; 
    } 

    public TValue LastValue 
    { 
     get; private set; 
    } 
} 
+0

Thông minh :-) Bạn có thể làm cho điều này gọn gàng hơn bằng cách sử dụng các thuộc tính tự động với những người định cư riêng và getters công cộng. –

+0

@Metro Smurf- rất đúng, cảm ơn. Tôi đã cập nhật mã để bao gồm những điều này- Tôi tin rằng nó làm cho ví dụ dễ đọc hơn một chút. – RichardOD

+0

Cách tốt hơn để thực hiện việc này là kế thừa từ điển và sau đó chỉ ghi đè phương thức Thêm, nơi bạn sẽ đặt thuộc tính đã thêm của mình, sau đó gọi base.Add (khóa, giá trị). Sẽ giúp bạn tiết kiệm rất nhiều rắc rối khi ủy nhiệm tất cả các chức năng của Từ điển theo cách thủ công. – sprite

1

Từ docs:

Đối với mục đích của liệt kê, mỗi mục trong từ điển được coi là cấu trúc khóa KeyValuePair đại diện cho giá trị và khóa của nó. Thứ tự trong đó các mục được trả lại là không xác định.

Vì vậy, tôi không nghĩ bạn có thể dựa vào Dictionary để trả về phần tử cuối cùng.

Sử dụng một bộ sưu tập khác. Có thể SortedDictionary ...

0

Từ điển không có nghĩa là được truy cập theo thứ tự, do đó, đầu tiên, cuối cùng không có ý nghĩa. Bạn có muốn giá trị được đánh chỉ mục bằng khóa cao nhất không?

Dictionary<double, string> dic = new Dictionary<double, string>(); 
double highest = double.MinValue; 
string result = null; 
foreach(double d in dic.keys) 
{ 
    if(d > highest) 
    { 
     result = dic[d]; 
     highest = d; 
    } 
} 
2

Thay vì sử dụng:

Dictionary<double, string> 

... bạn có thể sử dụng:

List<KeyValuePair<double, string>> 

này sẽ cho phép bạn sử dụng để truy cập vào indexer tố bằng cách đặt hàng thay vì bằng chìa khóa .

7

Tôi biết câu hỏi này là quá cũ để có được bất kỳ upvotes, nhưng tôi không thích bất kỳ câu trả lời như vậy sẽ gửi của riêng tôi với hy vọng cung cấp một tùy chọn cho độc giả trong tương lai.

Sau đây không làm việc cho tôi trên .NET 4.0:

myDictionary.Values.OrderBy(x => x.Key).Last(); 

tôi nghi ngờ vấn đề là 'x' đại diện cho một giá trị trong từ điển, và một giá trị không có chìa khóa (các từ điển lưu trữ khóa, giá trị từ điển không). Tôi cũng có thể mắc sai lầm khi sử dụng kỹ thuật này.

Dù bằng cách nào, giải pháp này sẽ chậm đối với các từ điển lớn, có lẽ O (n log n) cho CS folks, bởi vì nó là sắp xếp toàn bộ từ điển chỉ để có được một bài dự thi. Điều đó giống như sắp xếp lại toàn bộ bộ sưu tập DVD của bạn chỉ để tìm một bộ phim cụ thể.


var lastDicVal = dic.Values.Last(); 

cũng được thành lập như là một ý tưởng tồi. Trong thực tế, giải pháp này thực sự làm việc hầu hết thời gian do việc thực thi từ điển của Microsoft, nhưng trong các thuật ngữ kỹ thuật phần mềm là vô nghĩa và không nên dựa vào. Ngay cả khi nó hoạt động mọi lúc cho phần còn lại của đời đời, nó đại diện cho một thực hành mã hóa không an toàn, không an toàn.


Giải pháp của tôi là như sau:

var lastValue = dic[dic.Keys.Max()]; 

Các Keys.max() chức năng là nhanh hơn nhiều so với sắp xếp O (n) thay vì O (n log n). Nếu hiệu suất đủ quan trọng thậm chí O (n) quá chậm, khóa được chèn cuối cùng có thể được theo dõi trong một biến riêng biệt được sử dụng để thay thế dic.Keys.Max(), sẽ làm cho toàn bộ tra cứu O (1) cộng với bất kỳ chi phí nào tồn tại trong việc theo dõi mục nhập được chèn lần cuối.

0

Thay vì sử dụng LINQ như hầu hết các câu trả lời khác được đề xuất, bạn chỉ có thể truy cập phần tử cuối cùng của bất kỳ đối tượng Bộ sưu tập nào thông qua thuộc tính Đếm (xem ICollection.Count Property để biết thêm thông tin).

Xem mã ở đây cho một ví dụ về cách sử dụng số để truy cập vào các yếu tố cuối cùng trong bất kỳ Collection (bao gồm một từ điển):

Dictionary<double, string> dic = new Dictionary<double, string>(); 
var lastElementIndex = dic.Count - 1; 
var lastElement = dic[lastElementIndex]; 

Hãy ghi nhớ rằng đây trả về GIÁ TRỊ cuối cùng, không chìa khóa.

Các vấn đề liên quan