У меня есть словарь, что-то вроде
Dictionary<Foo,String> fooDict
Я просматриваю все в словаре, например
foreach (Foo foo in fooDict.Keys)
MessageBox.show(fooDict[foo]);
Он делает это в том порядке, в котором foo были добавлены в словарь, поэтому первый добавленный элемент - это первый возвращенный foo.
Как я могу изменить количество элементов, чтобы, например, третий добавленный foo был вторым возвращенным foo? Другими словами, я хочу изменить его «индекс».





Я не полностью обучен в данной области, чтобы правильно ответить на вопрос, но у меня есть чувство, что словарь сортирует значения в соответствии с ключом, чтобы выполнить быстрый поиск ключа. Это предполагает, что словарь отсортирован по ключевым значениям в соответствии с ключевым сравнением. Однако, глядя на методы объект, я предполагаю, что они используют хэш-коды для сравнения различных объектов, учитывая, что нет требований к типу, используемому для ключей. Это только предположение. Кто-то более осведомленный должен заполнить более подробную информацию.
Почему вы заинтересованы в манипулировании «индексом» словаря, когда его цель - индексировать произвольные типы?
Если вы прочитаете документацию на MSDN, вы увидите следующее:
«Порядок возврата товаров не определен».
Вы не можете оценить порядок, потому что Словарь - это не список или массив. Он предназначен для поиска значения по ключу, и любая возможность перебирать значения - это просто удобство, но порядок - это не поведение, от которого вы должны зависеть.
В .NET есть альтернативный объект, который позволяет поддерживать порядок в справочнике, см .: stackoverflow.com/questions/130614#130911
Не знаю, пригодится ли это кому-нибудь, но вот что я выяснил. Кажется, он работает (я имею в виду, что он не генерирует никаких исключений), но я все еще далек от возможности проверить, работает ли он так, как я надеюсь. Однако я делал подобное раньше.
public void sortSections()
{
//OMG THIS IS UGLY!!!
KeyValuePair<ListViewItem, TextSection>[] sortable = textSecs.ToArray();
IOrderedEnumerable<KeyValuePair<ListViewItem, TextSection>> sorted = sortable.OrderBy(kvp => kvp.Value.cardinality);
foreach (KeyValuePair<ListViewItem, TextSection> kvp in sorted)
{
TextSection sec = kvp.Value;
ListViewItem key = kvp.Key;
textSecs.Remove(key);
textSecs.Add(key, sec);
}
}
Вы "вероятно" в порядке, но, как я уже сказал, заказ не будет гарантирован. Бьюсь об заклад, что в тот момент, когда ему нужно изменить размер, он переупорядочит все в попытке. Почему ты вообще пользуешься словарем?
Желание связать элемент просмотра списка с настраиваемым объектом. Я уже делал это несколько раз в проекте, над которым работаю, но это первый раз, когда мощность действительно имеет значение.
Короткий ответ заключается в том, что способа быть не должно, поскольку Словарь «представляет собой набор ключей и значений». что не подразумевает какого-либо порядка. Любой взлом, который вы можете найти, выходит за рамки определения класса и может быть изменен.
Вы, вероятно, сначала должны спросить себя, действительно ли словарь нужен в этой ситуации, или вы можете обойтись без использования List of KeyValuePairs.
В противном случае может пригодиться что-то вроде этого:
public class IndexableDictionary<T1, T2> : Dictionary<T1, T2>
{
private SortedDictionary<int, T1> _sortedKeys;
public IndexableDictionary()
{
_sortedKeys = new SortedDictionary<int, T1>();
}
public new void Add(T1 key, T2 value)
{
_sortedKeys.Add(_sortedKeys.Count + 1, key);
base.Add(key, value);
}
private IEnumerable<KeyValuePair<T1, T2>> Enumerable()
{
foreach (T1 key in _sortedKeys.Values)
{
yield return new KeyValuePair<T1, T2>(key, this[key]);
}
}
public new IEnumerator<KeyValuePair<T1, T2>> GetEnumerator()
{
return Enumerable().GetEnumerator();
}
public KeyValuePair<T1, T2> this[int index]
{
get
{
return new KeyValuePair<T1, T2> (_sortedKeys[index], base[_sortedKeys[index]]);
}
set
{
_sortedKeys[index] = value.Key;
base[value.Key] = value.Value;
}
}
}
Когда клиентский код выглядит примерно так:
static void Main(string[] args)
{
IndexableDictionary<string, string> fooDict = new IndexableDictionary<string, string>();
fooDict.Add("One", "One");
fooDict.Add("Two", "Two");
fooDict.Add("Three", "Three");
// Print One, Two, Three
foreach (KeyValuePair<string, string> kvp in fooDict)
Console.WriteLine(kvp.Value);
KeyValuePair<string, string> temp = fooDict[1];
fooDict[1] = fooDict[2];
fooDict[2] = temp;
// Print Two, One, Three
foreach (KeyValuePair<string, string> kvp in fooDict)
Console.WriteLine(kvp.Value);
Console.ReadLine();
}
Обновлено: Почему-то не дает мне прокомментировать свой ответ.
В любом случае, IndexableDictionary отличается от OrderedDictionary тем, что
Разве это не воссоздание OrderedDictionary?
@ Spok16: он строго типизирован (нет снижения производительности упаковки / распаковки / других проблем), и к нему можно получить доступ с помощью индексов.
Возможно, вас заинтересует класс OrderedDicationary, который входит в пространство имен System.Collections.Specialized.
Если вы посмотрите на комментарии в самом низу, кто-то из MSFT опубликовал эту интересную заметку:
This type is actually misnamed; it is not an 'ordered' dictionary as such, but rather an 'indexed' dictionary. Although, today there is no equivalent generic version of this type, if we add one in the future it is likely that we will name such as type 'IndexedDictionary'.
Я думаю, было бы тривиально унаследовать от этого класса и создать общую версию OrderedDictionary.
Вау, я даже не подозревал, что такое существовало. Спасибо!
Мой словарь на самом деле Dictionary <ListViewItem, CustomObject>. Я хочу сделать так, чтобы когда пользователь переупорядочивал элементы в списке, он также переупорядочивал элементы в словаре, чтобы они выходили в том же порядке.