2008-09-17 6 views
16

Допустим, у меня есть словарь объект:В C# .NET 2.0, что является простым способом сделать foreach в обратном порядке?

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

Теперь я хочу перебирать словаря в обратном порядке. Я не могу использовать простой цикл, потому что я не знаю ключей словаря. Еогеасп легко:

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

Но как я могу выполнить это в обратном направлении?

ответ

19

Я бы использовал SortedList вместо словаря. Вы все равно можете получить к нему доступ с помощью Key, но вы также можете получить к нему доступ по индексу.

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); 

Следует отметить, что в сортированном списке хранятся пары ключ/значение, отсортированные по ключевым словам.

28

Словарь или любая другая форма хэш-таблицы не имеет порядка. Так что вы пытаетесь сделать, это бессмысленно :)

+0

Ах да. Duh. Я совершенно глуп. Спасибо :-) – Pandincus 2008-09-17 13:04:10

+0

Используйте SortedList, если вы хотите, чтобы поиск типов хеш-таблиц, а также порядок упорядочивания стиля Arrayylist. Кто-то уже разместил фрагмент кода. – Gishu 2008-09-17 13:41:33

+0

Конечно, хэш-таблица имеет заказ! – 2011-11-04 12:28:49

1

Это было бы Dictionary<int, SomeObject> myDictionary, и вы могли бы сделать это с помощью:

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

Если заказ является наиболее важным, вы могли бы вы Стек и создать простая структура для хранения вашей int, пары объектов.

18

Если у вас есть .NET 3.5, вы можете использовать метод расширения .Reverse() для IEnumerables. Например:

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

Единственный способ, которым я могу придумать в .NET 2.0 является первым скопировать все значения в списке, обратный список, а затем запустить Еогеасп в этом списке:

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

Я согласен с @pppie, но думаю, что вы заслуживаете ответа на вопрос в целом. Возможно, вы имели в виду, что вопрос был вообще, но случайно выбрал плохую структуру данных. Порядок значений в словаре следует рассматривать как специфичный для реализации; согласно документации, это всегда тот же порядок, что и ключи, но этот порядок также не указан.

В любом случае, нет простого способа сделать foreach работать в обратном порядке. Это синтаксический сахар для использования перечислителя класса, и перечисляющие могут перемещаться только в одном направлении. Технически ответ может быть «обратный сбор, а затем перечислить», но я думаю, что это тот случай, когда вы просто должны использовать «назад» для цикла:

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

Если вы хотите коллекцию словаря типа но вам необходимо сохранить порядок вставки, который вы можете посмотреть в KeyedCollection here

Это слияние словаря и списка. Таким образом, вы можете получить доступ к элементам в коллекции через ключ или индекс вставки.

Единственный доступ, если ваш элемент, хранящийся в коллекции, должен иметь ключ int. Если вы можете изменить это на строку или другой тип (Guid Mabye). Поскольку сбор 1 будет искать ключ 1, а не индекс 1.

0

Стандарт for будет лучше. Вам не нужно беспокоиться об обработке накладных расходов при обращении коллекции.

4

На самом деле, в C# 2.0 вы можете создать свой собственный итератор, который пересекает контейнер в обратном порядке. Затем вы можете использовать этот итератор в своем предложении foreach. Но ваш итератор должен был бы иметь способ навигации по контейнеру в первую очередь. Если это простой массив, он может идти в обратном направлении, как это:

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

Но, конечно, вы не можете сделать это с помощью словаря, поскольку это не реализует IList или предоставляет индексатор. Говорить, что словарь не имеет порядка, неверен: конечно, он имеет порядок. Этот порядок может быть даже полезен, если вы знаете, что это такое.

Для решения вашей проблемы: я бы сказал, скопируйте элементы в массив и воспользуйтесь описанным выше методом, чтобы пересечь его в обратном порядке. Как это:

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); 
    } 

} 

Копирование значений в массиве может показаться, что это плохая идея, но в зависимости от типа значения это не так уж плохо. Вы можете просто копировать ссылки!

0

Дословный ответ:

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

Если у вас нет .NET 3.5 и, следовательно, обратный метод расширения вы можете реализовать свой собственный. Я предполагаю, что это, вероятно, формирует промежуточный список (при необходимости) и перебирает в обратном направлении, что-то вроде следующего:

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; 
}