Check if KeyValuePair exists with LINQ's FirstOrDefault

Check if KeyValuePair exists with LINQ's FirstOrDefault

奢华的一滴泪 发布于 2021-11-26 字数 789 浏览 848 回复 6 原文

I have a dictionary of type

Dictionary<Guid,int>

I want to return the first instance where a condition is met using

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

However, how do I check if I'm actually getting back a KeyValuePair? I can't seem to use != or == to check against default(KeyValuePair) without a compiler error. There is a similar thread here that doesn't quite seem to have a solution. I'm actually able to solve my particular problem by getting the key and checking the default of Guid, but I'm curious if there's a good way of doing this with the keyvaluepair. Thanks

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一城柳絮吹成雪 2022-06-07 6 楼

A way to check against the default value of a struct such as KeyValuePair without specifying the type is to create a new instance using Activator:

if (available.Equals(Activator.CreateInstance(available.GetType())))
{
    Console.WriteLine("Not Found!");
}
半寸时光 2022-06-07 5 楼

you could check if

available.Key==Guid.Empty
中性美 2022-06-07 4 楼

What you want is an Any method that gives you the matching element as well. You can easily write this method yourself.

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;
  }
}
南烟 2022-06-07 3 楼

Use the default() keyword.

bool exists = !available.Equals(default(KeyValuePair<Guid, int>));
如梦 2022-06-07 2 楼

I suggest you change it in this way:

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

You can then see whether the list is empty or not, and take the first value if it's not, e.g.

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

Note that there's no real concept of a "first" entry in a dictionary - the order in which it's iterated is not well-defined. If you want to get the key/value pair which was first entered with that value, you'll need an order-preserving dictionary of some kind.

(This is assuming you actually want to know the key - if you're just after an existence check, Marc's solution is the most appropriate.)

孤独患者 2022-06-07 1 楼

If you just care about existence, you could use ContainsValue(0) or Any(p => p.Value == 0) instead? Searching by value is unusual for a Dictionary<,>; if you were searching by key, you could use TryGetValue.

One other approach:

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

This returns a class - so will be null if not found.