检查LINQ的FirstOrDefault是否存在KeyValuePair


75

我有一个类型的字典

Dictionary<Guid,int>

我想使用条件返回满足条件的第一个实例

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

但是,如何检查我是否真的在找回KeyValuePair?我似乎无法使用!=或==在没有编译器错误的情况下检查default(KeyValuePair)。有一个类似的线程在这里并不十分似乎有一个解决方案。实际上,我可以通过获取密钥并检查Guid的默认值来解决我的特定问题,但是我很好奇是否可以通过keyvaluepair做到这一点。谢谢


我发现这个回答另一个问题很有帮助。基本上使用.Where(),然后使用.Any()该结果来决定是否返回结果。
杰夫·B

Answers:


107

如果您只关心存在,可以使用ContainsValue(0)还是Any(p => p.Value == 0)替代?对于值,价值搜寻是不寻常的Dictionary<,>; 如果按键搜索,则可以使用TryGetValue

另一种方法:

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

这将返回一个-null如果找不到则将返回。


6
使用匿名类型伪装成结构,这是一个巧妙的技巧。我必须记住这一点。
Andre Luus 2012年

1
不,那不是我的意思。元组更简单,因此认为匿名类型“试图看起来像元组”并没有什么意义。我的评论背后的想法是,如果您使用var,则可以像上面所做的那样用匿名类型替换结构而无需任何参考修复。
Andre

1
匿名类方法是很好的方法,特别是如果您希望对找到的结果值做任何事情。省去了两次键入谓词的麻烦(一次检查.Any,第二次获取.First)。这是完美的,也正是我解决类似问题所需要的。
Mike Loux '16

1
请注意,您可以省略匿名类型的属性名称,就好像忽略它们一样,它们将自动使用分配的属性名称(在这种情况下是相同的)p => new { p.Key, p.Value }
oatsoda

26

我建议您以这种方式更改它:

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

然后,您可以查看列表是否为空,如果不是,则取第一个值,例如

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

请注意,字典中没有“第一个”条目的真实概念-迭代顺序不明确。如果要获取首次使用该值输入的键/值对,则需要某种保留顺序的字典。

(这是假设您实际上想知道密钥-如果只是在进行存在性检查之后,Marc的解决方案是最合适的。)


19

使用default()关键字。

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

1
我认为结果应该颠倒,因为:bool存在=!available.Equals(default(KeyValuePair <Guid,int>));
Jaime

9

您想要的是一种Any也为您提供匹配元素的方法。您可以自己轻松地编写此方法。

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

考虑到它与TryGetValue / TryParse的相似性,我想我可能将其称为TryGetFirst或TryFirst。
乔恩·斯基特

TryGetFirst非常好。但是最终您可以随便命名。
塞缪尔

(但是扩展方法的好主意-+1 :)
乔恩·斯凯特


-1

在不指定类型的情况下检查诸如KeyValuePair之类的结构的默认值的一种方法是使用Activator创建一个新实例:

if (available.Equals(Activator.CreateInstance(available.GetType())))
{
    Console.WriteLine("Not Found!");
}

我认为这可能类似于Florian使用default()关键字的答案。您的方法在运行时可能会变慢。
jm。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.