web-dev-qa-db-fra.com

Comment obtenir le nième élément d'un dictionnaire?

cipher = new Dictionary<char,int>;
cipher.Add( 'a', 324 );
cipher.Add( 'b', 553 );
cipher.Add( 'c', 915 );

Comment obtenir le 2ème élément? Par exemple, j'aimerais quelque chose comme:

KeyValuePair pair = cipher[1]

Où la paire contient ( 'b', 553 )


Sur la base de la suggestion de la coopérative à l'aide d'une liste, les choses fonctionnent:

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

En supposant que je suis correct que les éléments restent dans la liste dans l'ordre où ils sont ajoutés, je crois que je peux simplement utiliser un List par opposition à un SortedList comme suggéré.

34
Adam Kane

Le problème est qu'un dictionnaire n'est pas trié. Ce que vous voulez est un SortedList , qui vous permet d'obtenir des valeurs par index ainsi que par clé, bien que vous deviez peut-être spécifier votre propre comparateur dans le constructeur pour obtenir le tri que vous souhaitez. Vous pouvez ensuite accéder à une liste ordonnée des clés et valeurs et utiliser diverses combinaisons des méthodes IndexOfKey/IndexOfValue selon les besoins.

34
thecoop

comme ça:

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

notez que vous aurez également besoin d'une référence à Linq en haut de votre page ...

using System.Linq;
28
grenade

Avez-vous réellement besoin de rechercher par la clé? Sinon, utilisez un List<KeyValuePair<char, int>> (ou mieux encore, créez un type pour encapsuler le caractère et l'int).

Les dictionnaires ne sont pas intrinsèquement triés - les implémentations de dictionnaire qui sont triées dans .NET sont triées par clé, pas par ordre d'insertion.

Si vous devez accéder à la collection à la fois par ordre d'insertion et par clé, je vous recommande d'encapsuler une liste et un dictionnaire dans un seul type de collection.

Alternativement, si la liste va être assez courte, autorisez la recherche par index juste en faisant une recherche linéaire ...

17
Jon Skeet

Vous pouvez utiliser ElementAt() comme ceci:

cipher.ElementAt(index);

C'est mieux que l'option Select car de cette façon, vous n'avez pas à parcourir le dictionnaire:

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>
6
Sahil Mukheja

Juste pour m'accrocher à vos spécifications d'origine pour un dictionnaire, j'ai jeté du code et j'ai trouvé:

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

et il semble écrire le deuxième élément ("boule") sur la console de façon répétée. Si vous l'enveloppiez dans un appel de méthode pour obtenir le nième élément, cela fonctionnerait probablement. C'est assez moche, cependant. Si vous pouviez faire une SortedList à la place, comme le suggère @thecoop, vous feriez mieux.

2
Cyberherbalist

Il y avait une dupe de cette question posée ici: Comment récupérer le Nème élément dans le dictionnaire? . Il devrait être fermé bientôt, mais j'ai remarqué que les réponses manquent dans la nouvelle classe OrderedDictionary.

Il existe désormais (à partir de .NET 4), une classe OrderedDictionary . Cela permet des recherches rapides tout en fournissant des commandes. La méthode Item (Int32) renvoie le nième élément.

2
vipw

Vous pouvez appliquer la requête LINQ suivante sur votre "chiffrement" 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
Olioul Islam Rahi

C'est une vieille question, mais elle m'a été utile. Voici une implémentation que j'ai utilisée. Je voulais que le nième élément soit basé sur l'ordre d'insertion.

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();
  }
}
0
tony722