web-dev-qa-db-fra.com

Vérifiez si KeyValuePair existe avec FirstOrDefault de LINQ

J'ai un dictionnaire de type

Dictionary<Guid,int>

Je veux retourner la première instance où une condition est remplie en utilisant

var available = m_AvailableDict.FirstOrDefault(p => p.Value == 0)

Cependant, comment puis-je vérifier si je récupère réellement un KeyValuePair? Je n'arrive pas à utiliser! = Ou == pour vérifier par défaut (KeyValuePair) sans erreur de compilation. Il existe un fil similaire ici qui ne semble pas avoir de solution. En fait, je suis en mesure de résoudre mon problème particulier en obtenant la clé et en vérifiant la valeur par défaut de Guid, mais je suis curieux de savoir s'il existe un bon moyen de le faire avec la paire de valeurs de clés. Merci

71
Steve

Si vous vous souciez simplement de l'existence, vous pouvez utiliser ContainsValue(0) ou Any(p => p.Value == 0) à la place? La recherche par valeur est inhabituelle pour un Dictionary<,>; si vous recherchez par clé, vous pouvez utiliser TryGetValue.

Une autre approche:

var record = data.Where(p => p.Value == 1)
     .Select(p => new { Key = p.Key, Value = p.Value })
     .FirstOrDefault();

Cela retourne un classe - sera donc null si non trouvé.

103
Marc Gravell

Je vous suggère de le changer de cette façon:

var query = m_AvailableDict.Where(p => p.Value == 0).Take(1).ToList();

Vous pouvez alors voir si la liste est vide ou non, et prendre la première valeur si ce n'est pas le cas, par ex.

if (query.Count == 0)
{
    // Take action accordingly
}
else
{
    Guid key = query[0].Key;
    // Use the key
}

Notez qu'il n'y a pas de véritable concept d'une "première" entrée dans un dictionnaire - l'ordre dans lequel elle est itérée n'est pas bien défini. Si vous souhaitez obtenir la paire clé/valeur qui a été en premier entrée avec cette valeur, vous aurez besoin d'un dictionnaire de conservation d'ordre d'une sorte.

(Cela suppose que vous voulez réellement connaître la clé - si vous êtes juste après un contrôle d'existence, la solution de Marc est la plus appropriée.)

25
Jon Skeet

Utilisez le mot clé default ().

bool exists = !available.Equals(default(KeyValuePair<Guid, int>));
13

Ce que vous voulez, c'est une méthode Any qui vous donne également l'élément correspondant. Vous pouvez facilement écrire cette méthode vous-même.

public static class IEnumerableExtensions
{
  public static bool TryGetFirst<TSource>(this IEnumerable<TSource> source,
                                          Func<TSource, bool> predicate,
                                          out TSource first)
  {
    foreach (TSource item in source)
    {
      if (predicate(item))
      {
        first = item;
        return true;
      }
    }

    first = default(TSource);
    return false;
  }
}
9
Samuel

vous pouvez vérifier si

available.Key==Guid.Empty
2
pomarc