Как я могу получить n-й элемент из Словаря?
cipher = new Dictionary<char,int>;
cipher.Add( 'a', 324 );
cipher.Add( 'b', 553 );
cipher.Add( 'c', 915 );
Как получить второй элемент? Например, мне бы хотелось что-то вроде:
KeyValuePair pair = cipher[1]
Где пара содержит ( 'b', 553 )
На основе предложения о сотрудничестве с использованием списка все работает:
List<KeyValuePair<char, int>> cipher = new List<KeyValuePair<char, int>>();
cipher.Add( new KeyValuePair<char, int>( 'a', 324 ) );
cipher.Add( new KeyValuePair<char, int>( 'b', 553 ) );
cipher.Add( new KeyValuePair<char, int>( 'c', 915 ) );
KeyValuePair<char, int> pair = cipher[ 1 ];
Предполагая, что я прав, что элементы остаются в списке в том порядке, в котором они добавлены, я считаю, что я могу просто использовать List
в отличие от SortedList
, как было предложено.
Ответы
Ответ 1
Проблема заключается в том, что словарь не отсортирован. Вы хотите SortedList, который позволяет получать значения как по индексу, так и по ключу, хотя вам может потребоваться указать свой собственный компаратор в конструктор, чтобы получить сортировку, которую вы хотите. Затем вы можете получить доступ к упорядоченному списку ключей и значений и использовать различные комбинации методов IndexOfKey/IndexOfValue по мере необходимости.
Ответ 2
вот так:
int n = 0;
int nthValue = cipher[cipher.Keys.ToList()[n]];
обратите внимание, что вам также понадобится ссылка на Linq в верхней части страницы...
using System.Linq;
Ответ 3
Вам действительно нужно искать ключ? Если нет, используйте List<KeyValuePair<char, int>>
(или, еще лучше, создайте тип для инкапсуляции char и int).
Словари не сортируются по своему усмотрению - словарные реализации, которые сортируются в .NET, сортируются по ключу, а не по порядку вставки.
Если вам нужно получить доступ к коллекции с помощью порядка вставки и ключа, я бы рекомендовал инкапсулировать список и словарь в одном типе коллекции.
В качестве альтернативы, если список будет довольно коротким, разрешите поиск по индексу, просто выполнив линейный поиск...
Ответ 4
Чтобы цепляться за оригинальную спецификацию для Словаря, я перебросил код и придумал:
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("a", "apple");
d.Add("b", "ball");
d.Add("c", "cat");
d.Add("d", "dog");
int t = 0;
foreach (string s in d.Values)
{
t++;
if (t == 2) Console.WriteLine(s);
}
и, похоже, повторяется второй элемент ( "мяч" ) на консоли. Если вы завернете его в вызов метода для получения n-го элемента, это, вероятно, сработает. Это довольно уродливо. Если бы вы могли сделать SortedList вместо этого, как подсказывает @thecoop, вам будет лучше.
Ответ 5
Здесь был обманут этот вопрос: Как получить N-й элемент в словаре?. Он должен быть закрыт в ближайшее время, но я заметил, что в ответах здесь отсутствует новый класс OrderedDictionary.
Теперь (с .NET 4), OrderedDictionary класс. Это позволяет быстро выполнять поиск при заказе. Метод Item (Int32) возвращает n-й элемент.
Ответ 6
Вы можете использовать ElementAt()
следующим образом:
cipher.ElementAt(index);
Лучше, чем опция Select
, потому что вам не нужно перебирать словарь:
Документация
/// <summary>Returns the element at a specified index in a sequence.</summary>
/// <returns>The element at the specified position in the source sequence.</returns>
/// <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> to return an element from.</param>
/// <param name="index">The zero-based index of the element to retrieve.</param>
/// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="source" /> is null.</exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <paramref name="index" /> is less than 0 or greater than or equal to the number of elements in <paramref name="source" />.</exception>
Ответ 7
Вы можете применить следующий запрос LINQ к вашему 'cipher' Dictionary
var cipher = new Dictionary<char, int>();
cipher.Add('a', 324);
cipher.Add('b', 553);
cipher.Add('c', 915);
var nThValue = cipher.Select((Val, Index) => new { Val, Index })
.Single(viPair => viPair.Index == 1) //Selecting dictionary item with it index using index
.Val //Extracting KeyValuePair from dictionary item
.Value; //Extracting Value from KeyValuePair
Ответ 8
Это старый вопрос, но это было полезно для меня. Вот реализация, которую я использовал. Я хотел, чтобы n-й элемент был основан на порядке вставки.
public class IndexedDictionary<TKey, TValue> : IEnumerable<TValue> {
private List<TValue> list = new List<TValue>();
private Dictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>();
public TValue this[int index] { get { return list[index]; } }
public TValue this[TKey key] { get { return dict[key]; } }
public Dictionary<TKey, TValue>.KeyCollection Keys { get { return dict.Keys; } }
public int Count { get { return list.Count; } }
public int IndexOf(TValue item) { return list.IndexOf(item); }
public int IndexOfKey(TKey key) { return list.IndexOf(dict[key]); }
public void Add(TKey key, TValue value) {
list.Add(value);
dict.Add(key, value);
}
IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() {
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return list.GetEnumerator();
}
}
Ответ 9
НЕ пробуйте это: это была глупая идея - извините, ребята!
cipher.Values[1]
cipher.Keys[1]
', потому что элемент 2ND имеет индекс 1!