web-dev-qa-db-fra.com

Comment trouver un élément dans la collection de dictionnaires?

J'ai déclaré et rempli la collection suivante.

protected static Dictionary<string, string> _tags;

Maintenant, je veux rechercher une entrée particulière dans la collection. J'ai essayé ce qui suit.

thisTag = _tags.FirstOrDefault(t => t.Key == tag);
if (thisTag != default(KeyValuePair<string, string>))
    ...

Et je reçois l'erreur:

L'opérateur '! =' Ne peut pas être appliqué aux opérandes de type 'System.Collections.Generic.KeyValuePair' et ''

Au départ, j'ai essayé de comparer le résultat à null, et je suppose que ce n'est pas pris en charge avec structs.

J'aurais pensé que trouver un élément dans une collection est une tâche très triviale. Alors, comment diable pour déterminer si l'article que je recherche a été trouvé?

(Remarque: j'utilise Dictionary parce que je veux des recherches rapides. Je sais que je peux utiliser Contains() pour déterminer si l'élément est là. Mais cela signifie un total de deux recherches, qui trient de défaites le but d'avoir une recherche rapide. J'utiliserai volontiers une collection différente si elle peut rechercher rapidement un élément et j'ai un moyen de déterminer si elle a réussi.)

34
Jonathan Wood
thisTag = _tags.FirstOrDefault(t => t.Key == tag);

est une manière inefficace et un peu étrange de trouver quelque chose par clé dans un dictionnaire. La recherche d'une clé est la fonction de base d'un dictionnaire.

La solution de base serait:

if (_tags.Containskey(tag)) { string myValue = _tags[tag]; ... }

Mais cela nécessite 2 recherches.

TryGetValue(key, out value) est plus concis et efficace, il ne fait qu'une seule recherche. Et cela répond à la dernière partie de votre question, la meilleure façon de faire une recherche est:

string myValue;
if (_tags.TryGetValue(tag, out myValue)) { /* use myValue */ }

Mise à jour VS 2017, pour C # 7 et au-delà, nous pouvons déclarer la variable de résultat en ligne:

if (_tags.TryGetValue(tag, out string myValue))
{
    // use myValue;
}
// use myValue, still in scope, null if not found
92
Henk Holterman

Parfois, vous devez toujours utiliser FirstOrDefault si vous devez faire différents tests. Si le composant Key de votre dictionnaire est nullable, vous pouvez le faire:

thisTag = _tags.FirstOrDefault(t => t.Key.SubString(1,1) == 'a');
if(thisTag.Key != null) { ... }

À l'aide de FirstOrDefault, la clé et la valeur de KeyValuePair retournées seront toutes deux nulles si aucune correspondance n'est trouvée.

7
igelineau

Il est possible de trouver l'élément dans la collection Dictionary en utilisant ContainsKey ou TryGetValue comme suit:

class Program
{
    protected static Dictionary<string, string> _tags = new Dictionary<string,string>();

    static void Main(string[] args)
    {
        string strValue;

        _tags.Add("101", "C#");
        _tags.Add("102", "ASP.NET");

        if (_tags.ContainsKey("101"))
        {
            strValue = _tags["101"];
            Console.WriteLine(strValue);
        }

        if (_tags.TryGetValue("101", out strValue))
        {
            Console.WriteLine(strValue);
        }
    }
}
0
BoiHue

Bien sûr, si vous voulez vous assurer qu'il est là, sinon échouez, cela fonctionne:

thisTag = _tags [clé];

REMARQUE: cela échouera si la paire clé/valeur n'existe pas, mais parfois c'est exactement ce que vous voulez. De cette façon, vous pouvez l'attraper et faire quelque chose pour corriger l'erreur. Je ne ferais cela que si je suis certain que la paire clé/valeur est ou devrait être dans le dictionnaire et sinon je veux qu'il le sache via le lancer.

0
Mac