How do I get the nth element from a Dictionary?

0 votes
asked Jul 23, 2009 by adam-kane
cipher = new Dictionary<char,int>;
cipher.Add( 'a', 324 );
cipher.Add( 'b', 553 );
cipher.Add( 'c', 915 );

How to get the 2nd element? For example, I'd like something like:

KeyValuePair pair = cipher[1]

Where pair contains ( 'b', 553 )


Based on the coop's suggestion using a List, things are working:

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

Assuming that I'm correct that the items stay in the list in the order they are added, I believe that I can just use a List as opposed to a SortedList as suggested.

9 Answers

0 votes
answered Jul 23, 2009 by n8wrl

Do NOT try this: This was a dumb idea - sorry guys!

cipher.Values[1]
cipher.Keys[1]

'cause the 2ND element is index 1!

0 votes
answered Jul 23, 2009 by thecoop

The problem is a Dictionary isn't sorted. What you want is a SortedList, which allows you to get values by index as well as key, although you may need to specify your own comparer in the constructor to get the sorting you want. You can then access an ordered list of the Keys and Values, and use various combinations of the IndexOfKey/IndexOfValue methods as needed.

0 votes
answered Jul 23, 2009 by cyberherbalist

Just to cling to your original spec for a Dictionary, I slung some code and came up with:

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

and it does seem to write the second item ("ball") to the console repeatably. If you wrapped it into a method call to get the nth element, it would probably work. This is pretty ugly, though. If you could do a SortedList instead, as @thecoop suggests, you'd be better off.

0 votes
answered Jul 23, 2009 by grenade

like this:

int n = 0;
int nthValue = cipher[cipher.Keys.ToList()[n]];

note that you will also need a reference to Linq at the top of your page...

using System.Linq;
0 votes
answered Jul 23, 2009 by jon-skeet

Do you actually need to look up by the key? If not, use a List<KeyValuePair<char, int>> (or better yet, create a type to encapsulate the char and the int).

Dictionaries aren't inherently sorted - the dictionary implementations which are sorted in .NET are sorted by key, not by insertion order.

If you need to access the collection by both insertion order and key, I'd recommend encapsulating a List and a Dictionary in a single collection type.

Alternatively, if the list is going to be quite short, allow lookup by index just by doing a linear search...

0 votes
answered Jul 17, 2011 by vipw

There was a dupe of this question asked here: How to retrieve Nth item in dictionary?. It should be closed soon, but I noticed that the answers here are missing the new OrderedDictionary class.

There is now (as of .NET 4), an OrderedDictionary class. This allows fast lookups while providing ordering. The Item(Int32) method returns the nth element.

0 votes
answered Jul 17, 2015 by olioul-islam-rahi

You can apply the following LINQ query on your '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's index using index
            .Val                                   //Extracting KeyValuePair from dictionary item
            .Value;                                //Extracting Value from KeyValuePair
0 votes
answered Sep 15, 2017 by sahil-mukheja

You can use ElementAt() like this:

cipher.ElementAt(index);

Its better than than the Select option because this way you don't have to loop through the dictionary:

documentation

/// <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>
0 votes
answered Sep 15, 2017 by tony722

This is an old question, but it was helpful to me. Here's an implementation that I used. I wanted the nth element to be based on the insertion order.

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();
  }
}
Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...