2008-09-17 37 views
16

phép nói rằng tôi có một đối tượng từ điển:Trong C# .NET 2.0, một cách dễ dàng để làm một foreach ngược lại là gì?

Dictionary myDictionary<int, SomeObject> = new Dictionary<string, SomeObject>(); 

Bây giờ tôi muốn lặp qua hết từ điển theo thứ tự ngược. Tôi không thể sử dụng vòng lặp đơn giản vì tôi không biết các phím của từ điển. Một foreach là dễ dàng:

foreach (SomeObject object in myDictionary.Values) 
{ 
    // Do stuff to object 
} 

Nhưng làm thế nào tôi có thể thực hiện điều này ngược lại?

Trả lời

19

Tôi muốn sử dụng SortedList thay vì từ điển. Bạn vẫn có thể truy cập nó bằng Khóa, nhưng bạn cũng có thể truy cập nó theo chỉ mục.

SortedList sCol = new SortedList(); 

sCol.Add("bee", "Some extended string matching bee"); 
sCol.Add("ay", "value matching ay"); 
sCol.Add("cee", "Just a standard cee"); 

// Go through it backwards. 
for (int i = sCol.Count - 1; i >=0 ; i--) 
    Console.WriteLine("sCol[" + i.ToString() + "] = " + sCol.GetByIndex(i)); 

// Reference By Key 
foreach (string i in sCol.Keys) 
    Console.WriteLine("sCol[" + i + "] = " + sCol[i]); 

// Enumerate all values 
foreach (string i in sCol.Values) 
    Console.WriteLine(i); 

Cần lưu ý rằng danh sách được sắp xếp lưu trữ cặp khóa/giá trị được sắp xếp theo khóa.

28

Từ điển hoặc bất kỳ hình thức nào khác của hashtable không có thứ tự. Vì vậy, những gì bạn đang cố gắng làm là vô nghĩa :)

+0

Oh yeah. Duh. Tôi hoàn toàn ngu ngốc. Cảm ơn :-) – Pandincus

+0

Sử dụng SortedList nếu bạn muốn tra cứu kiểu hashtable cũng như sắp xếp thứ tự dãy kiểu danh sách. Ai đó đã đăng một đoạn mã. – Gishu

+0

Tất nhiên một hashtable đã đặt hàng! –

1

Đó sẽ là một Dictionary<int, SomeObject> myDictionary, và bạn sẽ làm điều đó bằng cách:

foreach(SomeObject _object in myDictionary.Values.Reverse()) 
{ 
} 
0

Nếu thứ tự là quan trọng nhất, bạn có thể quý khách Stack và tạo ra một cấu trúc đơn giản để lưu trữ cặp int, Object của bạn.

18

Nếu bạn có .NET 3.5, bạn có thể sử dụng phương thức mở rộng .Reverse() trên IEnumerables. Ví dụ:

foeach (SomeObject o in myDictionary.Values.Reverse()) 
{ 
    // Do stuff to object 
} 
+2

bạn sẽ cần phải tham khảo -> using System.Linq; –

1

Cách duy nhất tôi có thể nghĩ ra trong .NET 2.0 là trước hết phải sao chép tất cả các giá trị vào một danh sách, đảo ngược danh sách và sau đó chạy foreach trong danh sách đó:

Dictionary<int, object> d; 
List<object> tmplist; 
foreach (object o in d.Values) tmplist.Add(s); 
tmplist.Reverse(); 
foreach (object o in tmplist) { 
    //Do stuff 
} 
3

Tôi đồng ý với @leppie, nhưng nghĩ rằng bạn xứng đáng được trả lời cho câu hỏi nói chung. Nó có thể là bạn có nghĩa là cho câu hỏi nói chung, nhưng vô tình chọn một cấu trúc dữ liệu xấu. Thứ tự của các giá trị trong một từ điển nên được xem xét cụ thể cho việc triển khai thực hiện; theo tài liệu, nó luôn luôn theo thứ tự như các khóa, nhưng thứ tự này cũng không được chỉ định.

Dù sao, không có cách nào đơn giản để làm cho foreach hoạt động ngược lại. Đó là đường cú pháp để sử dụng điều tra của lớp, và các điều tra viên chỉ có thể đi theo một hướng. Về mặt kỹ thuật, câu trả lời có thể là "đảo ngược bộ sưu tập, sau đó liệt kê", nhưng tôi nghĩ đây là trường hợp bạn sẽ chỉ phải sử dụng "ngược" cho vòng lặp:

for (int i = myCollection.Length - 1; i >= 0; i--) 
{ 
    // do something 
}
+1

Điều đó sẽ không hoạt động vì bộ sưu tập mà thuộc tính "Giá trị" của lớp trả về từ điển, không có trình chỉ mục. –

0

Nếu bạn muốn bộ sưu tập từ điển nhưng bạn cần phải duy trì thứ tự chèn, bạn có thể xem xét KeyedCollection here

Đó là sự hợp nhất giữa từ điển và danh sách. Bằng cách đó bạn có thể truy cập các phần tử trong bộ sưu tập thông qua khóa hoặc chỉ mục chèn.

Bí quyết duy nhất là nếu phần tử của bạn được lưu trữ trong bộ sưu tập phải có khóa int. Nếu bạn có thể thay đổi thành chuỗi hoặc loại khác (Guid Mabye). Vì bộ sưu tập 1 sẽ tìm kiếm khóa 1 chứ không phải chỉ mục của 1.

0

Vòng lặp tiêu chuẩn for sẽ là tốt nhất. Bạn không phải lo lắng về chi phí xử lý của việc đảo ngược bộ sưu tập.

4

Thực ra, trong C# 2.0, bạn có thể tạo trình vòng lặp của riêng bạn để truyền tải một vùng chứa ngược lại. Sau đó, bạn có thể sử dụng trình lặp đó trong báo cáo foreach của bạn. Nhưng trình lặp của bạn sẽ phải có cách điều hướng vùng chứa ở vị trí đầu tiên. Nếu đó là một mảng đơn giản, nó có thể quay ngược lại như sau:

static IEnumerable<T> CreateReverseIterator<T>(IList<T> list) 
{ 
    int count = list.Count; 
    for (int i = count - 1; i >= 0; --i) 
    { 
     yield return list[i]; 
    } 
} 

Nhưng tất nhiên bạn không thể làm điều đó bằng từ điển vì nó không thực hiện IList hoặc cung cấp trình chỉ mục. Nói rằng một từ điển không có thứ tự là không đúng: tất nhiên nó có trật tự. Thứ tự đó thậm chí có thể hữu ích nếu bạn biết nó là gì.

Để biết giải pháp cho vấn đề của bạn: Tôi muốn nói sao chép các phần tử vào một mảng và sử dụng phương pháp trên để truyền tải nó ngược lại. Như thế này:

static void Main(string[] args) 
{ 
    Dictionary<int, string> dict = new Dictionary<int, string>(); 

    dict[1] = "value1"; 
    dict[2] = "value2"; 
    dict[3] = "value3"; 

    foreach (KeyValuePair<int, string> item in dict) 
    { 
     Console.WriteLine("Key : {0}, Value: {1}", new object[] { item.Key, item.Value }); 
    } 

    string[] values = new string[dict.Values.Count]; 
    dict.Values.CopyTo(values, 0); 

    foreach (string value in CreateReverseIterator(values)) 
    { 
     Console.WriteLine("Value: {0}", value); 
    } 

} 

Sao chép giá trị vào một mảng có thể có vẻ không tốt, nhưng tùy thuộc vào loại giá trị không thực sự tệ. Bạn có thể chỉ cần sao chép tài liệu tham khảo!

0

câu trả lời Literal:

Dictionary<int, SomeObject> myDictionary = new Dictionary<int, SomeObject>(); 

foreach (var pair in myDictionary.OrderByDescending(i => i.Key)) 
{ 
    //Observe pair.Key 
    //Do stuff to pair.Value 
} 
3

Nếu bạn không có .NET 3.5 và do đó phương pháp khuyến nông Xếp bạn có thể thực hiện của riêng bạn. Tôi đoán nó có thể tạo ra một danh sách trung gian (khi cần thiết) và lặp nó ngược lại, giống như sau:

public static IEnumerable<T> Reverse<T>(IEnumerable<T> items) 
{ 
    IList<T> list = items as IList<T>; 
    if (list == null) list = new List<T>(items); 
    for (int i = list.Count - 1; i >= 0; i--) 
    { 
     yield return list[i]; 
    } 
} 
-2
foreach (Sample in Samples) 

try the following: 

Int32 nEndingSample = Samples.Count - 1; 

for (i = nEndingSample; i >= 0; i--) 
{ 
    x = Samples[i].x; 
    y = Samples[i].y; 
} 
Các vấn đề liên quan