Dictionary.FirstOrDefault() 如何确定是否找到结果

发布于 2024-10-25 22:09:45 字数 838 浏览 1 评论 0原文

我有(或想要有)一些像这样的代码:

IDictionary<string,int> dict = new Dictionary<string,int>();
// ... Add some stuff to the dictionary.

// Try to find an entry by value (if multiple, don't care which one).
var entry = dict.FirstOrDefault(e => e.Value == 1);
if ( entry != null ) { 
   // ^^^ above gives a compile error:
   // Operator '!=' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<string,int>' and '<null>'
}

我也尝试像这样更改有问题的行:

if ( entry != default(KeyValuePair<string,int>) ) 

但这也给出了编译错误:

Operator '!=' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<string,int>' and 'System.Collections.Generic.KeyValuePair<string,int>'

这里给出了什么?

I have (or wanted to have) some code like this:

IDictionary<string,int> dict = new Dictionary<string,int>();
// ... Add some stuff to the dictionary.

// Try to find an entry by value (if multiple, don't care which one).
var entry = dict.FirstOrDefault(e => e.Value == 1);
if ( entry != null ) { 
   // ^^^ above gives a compile error:
   // Operator '!=' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<string,int>' and '<null>'
}

I also tried changing the offending line like this:

if ( entry != default(KeyValuePair<string,int>) ) 

But that also gives a compile error:

Operator '!=' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<string,int>' and 'System.Collections.Generic.KeyValuePair<string,int>'

What gives here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

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

评论(8

朕就是辣么酷 2024-11-01 22:09:50

对于可空值类型,只需检查即可。

if ( entry.Value != null ) { 
     //do stuff
} 

对于不可为 null 的类型,检查默认值;对于 int,检查默认值 0。

if ( entry.Value != 0) { 
   //do stuff
} 

for nullable value types, just check.

if ( entry.Value != null ) { 
     //do stuff
} 

for non-nullable types check againts default value, for int, 0.

if ( entry.Value != 0) { 
   //do stuff
} 
戏蝶舞 2024-11-01 22:09:50

公平地说,强制转换对象或使用 select 语句是不必要的,我也不会依赖 try catch 来解决问题。

既然您无论如何都在使用 Linq,那么使用 .Any 有什么问题吗?

var entry;
if (dict.Any(e => e.Value == 1))
{
    // Entry was found, continue work...
    entry = dict.FirstOrDefault(e => e.Value == 1);
}
else
{
    // Entry was not found.
    entry = -1;
}

显然,请使用它来适应您的解决方案,但这是一个相当快速的检查,如果它在集合中找到具有该值的项目,则会停止。因此,如果找到匹配项,它不会检查所有值。

MSDN 文档:
https://msdn.microsoft.com/en -us/library/bb534972(v=vs.110).aspx

To be fair, casting the object or using a select statement is unnecessary, I wouldn't rely on a try catch to fix the issue either.

Since you're using Linq anyway, what's wrong with using .Any?

var entry;
if (dict.Any(e => e.Value == 1))
{
    // Entry was found, continue work...
    entry = dict.FirstOrDefault(e => e.Value == 1);
}
else
{
    // Entry was not found.
    entry = -1;
}

Obviously, play with it to fit your solution, but it's a fairly quick check that stops if it finds an item in the collection with that value. So it won't check all values if a match has been found.

MSDN Documentation:
https://msdn.microsoft.com/en-us/library/bb534972(v=vs.110).aspx

缱绻入梦 2024-11-01 22:09:50

应用于 Dictionary 的 Linq FirstOrDefault 无论如何都会返回不可为 null 的 keyValuePair 对象。
正确的方法是检查结果键或值是否不等于默认类型值

Linq FirstOrDefault applying to a Dictionary returns not nullable keyValuePair object anyway.
The right way is to check result key or value that it doesn't equal default type value

帅气尐潴 2024-11-01 22:09:49

这样做:

if ( entry.Key != null )

问题是 FirstOrDefault 方法返回一个 KeyValuePair是一个值类型,因此它永远不可能是null。您必须通过检查其 KeyValue 属性中至少一个是否具有默认值来确定是否找到某个值。 Key 的类型为 string,因此考虑到字典中不能包含带有 null< 的项目,因此检查 null 是有意义的/代码> 键。

您可以使用的其他方法:

var entry = dict.Where(e => e.Value == 1)
                .Select(p => (int?)p.Value)
                .FirstOrDefault();

这会将结果投影到可空整数的集合中,如果该集合为空(没有结果),您将得到一个空值 - 您不可能将其误认为是 int成功的搜索将会产生结果。

Do it this way:

if ( entry.Key != null )

The thing is that the FirstOrDefault method returns a KeyValuePair<string, int> which is a value type, so it cannot ever be null. You have to determine if a value was found by checking if at least one of its Key, Value properties has its default value. Key is of type string, so checking that for null makes sense considering that the dictionary could not have an item with a null key.

Other approaches you could use:

var entry = dict.Where(e => e.Value == 1)
                .Select(p => (int?)p.Value)
                .FirstOrDefault();

This projects the results into a collection of nullable ints, and if that is empty (no results) you get a null -- there's no way you can mistake that for the int that a successful search would yield.

栀梦 2024-11-01 22:09:49

无论 Key 和 Value 的类型如何,您都可以执行以下操作:

    static void Main(string[] args)
    {
        var dict = new Dictionary<int, string>
        {
            {3, "ABC"},
            {7, "HHDHHGKD"}
        };

        bool found = false;
        var entry = dict.FirstOrDefault(d => d.Key == 3 && (found=true));
        if (found)
        {
            Console.WriteLine("found: " + entry.Value);
        }
        else
        {
            Console.WriteLine("not found");
        }
        Console.ReadLine();
    }

Regardless of the types of Key and Value, you could do something like this:

    static void Main(string[] args)
    {
        var dict = new Dictionary<int, string>
        {
            {3, "ABC"},
            {7, "HHDHHGKD"}
        };

        bool found = false;
        var entry = dict.FirstOrDefault(d => d.Key == 3 && (found=true));
        if (found)
        {
            Console.WriteLine("found: " + entry.Value);
        }
        else
        {
            Console.WriteLine("not found");
        }
        Console.ReadLine();
    }
你丑哭了我 2024-11-01 22:09:49

我认为最清晰的代码是这样的:

if (dict.ContainsValue(value))
  string key = dict.First(item => item.Value == value).Key;
else
  // do somehing else

虽然从速度的角度来看这不太好,但也没有更好的解决方案。这意味着第二次会以慢速搜索字典。 Dictionary 类应该通过提供方法“bool TryGetKey(value)”来改进。它看起来有点奇怪 - 因为字典被认为是在另一个方向使用 - 但有时向后翻译是不可避免的。

The clearest code I think is this:

if (dict.ContainsValue(value))
  string key = dict.First(item => item.Value == value).Key;
else
  // do somehing else

Though from the standpoint of speed it's not nice, but there is no better solution. This means that the dictionary will be searched with a slow search a second time. The Dictionary class should be improved by offering a method 'bool TryGetKey(value)'. It looks a little bit strange - because a dictionary is thought to be used in the other direction - but sometimes it's unavoidable to translate backwards.

爱她像谁 2024-11-01 22:09:49
public static TValue FirstOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, Func<KeyValuePair<TKey, TValue>, bool> where)
    {
        foreach (var kv in dictionary)
        {
            if (where(kv))
                return kv.Value;
        }
        return default;
    }
public static TValue FirstOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, Func<KeyValuePair<TKey, TValue>, bool> where)
    {
        foreach (var kv in dictionary)
        {
            if (where(kv))
                return kv.Value;
        }
        return default;
    }
素罗衫 2024-11-01 22:09:48

乔恩的答案将适用于 Dictionary,因为字典中不能有空键值。但是,它不适用于 Dictionary,因为它不代表空键值...“失败”模式最终会出现键为 0。

两个选项:

编写一个 TryFirstOrDefault 方法,如下所示:

public static bool TryFirstOrDefault<T>(this IEnumerable<T> source, out T value)
{
    value = default(T);
    using (var iterator = source.GetEnumerator())
    {
        if (iterator.MoveNext())
        {
            value = iterator.Current;
            return true;
        }
        return false;
    }
}

或者,投影为可空类型:

var entry = dict.Where(e => e.Value == 1)
                .Select(e => (KeyValuePair<string,int>?) e)
                .FirstOrDefault();

if (entry != null)
{
    // Use entry.Value, which is the KeyValuePair<string,int>
}

Jon's answer will work with Dictionary<string, int>, as that can't have a null key value in the dictionary. It wouldn't work with Dictionary<int, string>, however, as that doesn't represent a null key value... the "failure" mode would end up with a key of 0.

Two options:

Write a TryFirstOrDefault method, like this:

public static bool TryFirstOrDefault<T>(this IEnumerable<T> source, out T value)
{
    value = default(T);
    using (var iterator = source.GetEnumerator())
    {
        if (iterator.MoveNext())
        {
            value = iterator.Current;
            return true;
        }
        return false;
    }
}

Alternatively, project to a nullable type:

var entry = dict.Where(e => e.Value == 1)
                .Select(e => (KeyValuePair<string,int>?) e)
                .FirstOrDefault();

if (entry != null)
{
    // Use entry.Value, which is the KeyValuePair<string,int>
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文