从值获取键 - 字典<string,List<string>>

11

我想通过指定一个值来获取密钥,但是遇到了麻烦。你能告诉我最好的实现方法吗?

var st1= new List<string> { "NY", "CT", "ME" };
var st2= new List<string> { "KY", "TN", "SC" };
var st3= new List<string> { "TX", "OK", "MO" };
var statesToEmailDictionary = new Dictionary<string, List<string>>();
statesToEmailDictionary.Add("test1@gmail.com", st1);
statesToEmailDictionary.Add("test2@gmail.com", st2);
statesToEmailDictionary.Add("test3@gmail.com", st3);

var emailAdd = statesToEmailDictionary.FirstOrDefault(x => x.Value.Where(y => y.Contains(state))).Key;
7个回答

19

FirstOrDefault返回的值将是一个KeyValuePair<string, List<string>>,所以要获取键,只需使用Key属性。像这样:

var emailAdd = statesToEmailDictionary
    .FirstOrDefault(x => x.Value.Contains(state))
    .Key;

或者,以下是查询语法的等效方式:

var emailAdd = 
    (from p in statesToEmailDictionary
     where p.Value.Contains(state)
     select p.Key)
    .FirstOrDefault();

FirstOrDefault(...).Key 不是很危险吗?如果在这里发生 "OrDefault",会导致意外行为。 - Chris Marisic
2
@ChrisMarisic 'OrDefault' 情况返回您正在迭代的类型的默认值。对于引用类型,它是 null,但对于值类型,它将是该类型的新实例。由于 KeyValuePair<TKey, TValue> 是一个值类型(即一个 struct),因此 'OrDefault' 情况不会导致空引用异常。由于这里的 TKeystring,所以该新实例的 .Key 将为 null - p.s.w.g

2

这个帖子中没有提到的是,FirstOrDefault方法只能通过Linq使用:

using System;
using System.Collections.Generic;
// FirstOrDefault is part of the Linq API
using System.Linq;

namespace Foo {
    class Program {
        static void main (string [] args) {
            var d = new Dictionary<string, string> () {
                { "one", "first" },
                { "two", "second" },
                { "three", "third" }
            };
            Console.WriteLine (d.FirstOrDefault (x => x.Value == "second").Key);
        }
    }
}

2
我认为您想要的是:

我认为您想要:

var emailAdd = statesToEmailDictionary.FirstOrDefault(x => x.Value.Any(y => y.Contains(state))).Key;

1
var emailAdd = statesToEmailDictionary
    .FirstOrDefault(x => x.Value != null && x.Value.Contains(state))
    .Key;

但是如果你在寻求性能方面的优化,我建议反转你的字典,并创建一个<state, email>的字典来实现你所需要的功能。

// To handle when it's not in the results
string emailAdd2 = null;
foreach (var kvp in statesToEmailDictionary)
{
    if (kvp.Value != null && kvp.Value.Contains(state))
    {
        emailAdd2 = kvp.Key;
        break;
    }
}

有没有处理 NullReferenceException 的方法? - Ilya Ivanov
我认为至少不能用一行代码实现。使用非LINQ检查进行编辑。它执行与LINQ相同的操作-循环遍历每个值,直到找到一个值,然后跳出循环。如果从未找到,则保留null的原始值。 - Joe Enos
1
实际上,如果您收到了NullReferenceException异常,则列表本身必须为null。您可以在lambda内部处理它。已更新。 - Joe Enos

1
var emailAdd = statesToEmailDictionary.First(x=>x.Value.Contains(state)).Key;

0

只需简单的Linq就可以做到这一点

Dim mKP = (From mType As KeyValuePair(Of <Key type>, <Value type>) In <Dictionary>
           Where mType.Value = <value seeked> Select mType).ToList

If mKP.Count > 0 then
    Dim value as <value type> = mKP.First.Value
    Dim key as <Key type> = mKP.First.Key 
End if 

当然,如果存在重复的值,这将返回多个 KeyValuePair


-1
var temp = statesToEmailDictionary.Where( x => x.Value.Contains(state)).FirstOrDefault();
var emailAdd = temp != null ? temp.Key : string.Empty;

1
KeyValuePair<T, U>是一个结构体,因此temp永远不会为空。 - p.s.w.g
我有一个相同的用例,需要在键=key时获取值=value,其中key=test1@gmail.com。我尝试了下面的代码,但没有得到预期的输出结果。var emailAdd = statesToEmailDictionary.FirstOrDefault(x => x.Key == "test1@gmail.com").Value; - Blossom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接