用 C# 从 List<KeyValuePair<string, string>> 中获取键和值

22

给定一个列表:

    private List<KeyValuePair<string, string>> KV_List = new List<KeyValuePair<string, string>>();
    void initList()
    {
        KV_List.Add(new KeyValuePair<string, string>("qwer", "asdf"));
        KV_List.Add(new KeyValuePair<string, string>("qwer", "ghjk"));
        KV_List.Add(new KeyValuePair<string, string>("zxcv", "asdf"));
        KV_List.Add(new KeyValuePair<string, string>("hjkl", "uiop"));
    }

(注意:关键字“qwer”有多个值,值“asdf”也有多个对应的关键字。)

1)是否有更好的方法返回所有关键字的列表而不只是在KeyValuePair列表上执行foreach循环?

2)同样地,是否有更好的方法返回给定关键字的所有值的列表,而不使用foreach?

3)那么,如何返回给定值的所有关键字的列表?

谢谢...


你可以像这样使用 multimap 吗?(https://dev59.com/eXRC5IYBdhLWcg3wMeDf) - ntohl
7个回答

35
// #1: get all keys (remove Distinct() if you don't want it)
List<string> allKeys = (from kvp in KV_List select kvp.Key).Distinct().ToList();
// allKeys = { "qwer", "zxcv", "hjkl" }

// #2: get values for a key
string key = "qwer";
List<string> values = (from kvp in KV_List where kvp.Key == key select kvp.Value).ToList();
// values = { "asdf", "ghjk" }

// #3: get keys for a value
string value = "asdf";
List<string> keys = (from kvp in KV_List where kvp.Value == value select kvp.Key).ToList();
// keys = { "qwer", "zxcv" }

如何在动态列表中使用相同的内容 - Sam

6
您可以使用 System.Collection.Specialized 命名空间中的 NameValueCollection:
NameValueCollection  KV_List = new NameValueCollection();

KV_List.Add("qwer", "asdf");
KV_List.Add("qwer", "ghjk");
KV_List.Add("zxcv", "asdf");
KV_List.Add("hjkl", "uiop");

使用示例:

string singleValue = KV_List["zxcv"];  // returns "asdf"
string[] values = KV_List.GetValues("qwer");  // returns "asdf, "ghjk"
string[] allKeys = KV_List.AllKeys;
string[] allValues = KV_List.AllKeys;

https://msdn.microsoft.com/en-us/library/system.collections.specialized.namevaluecollection%28v=vs.110%29.aspx


5

听起来你会受益于使用类似以下的东西:

Dictionary<string, List<string>> kvlist;

kvlist["qwer"] = new List<string>();
kvlist["qwer"].Add("value1");
kvlist["qwer"].Add("value2");

foreach(var value in kvlist["qwer"]) {
    // do something
}

使用字典和列表可以相对容易地创建一个基本的多值字典类。

这篇博客文章更详细地介绍了微软通过NuGet提供的MultiDictionary类型。


很遗憾,我无法控制这个列表(我必须“按原样处理”)... - frog_jr
啊,那太糟糕了。几个基于Linq的答案应该能满足您的需求(虽然它们会更语法友好,但它们不会比简单循环更高效)。如果您可以确保列表始终按键值排序,则可以将性能从O(n)提高到O(log n)。 - Robert Horvick
通常情况下,它是未排序的(无论是按键还是值),但列表中只有几千个条目。我可能会选择其中一个linq答案,它们将“看起来”更干净,以便未来查看代码的任何人都能轻松理解。 :) - frog_jr

4
你可以使用LINQ来实现。但是从性能的角度来看,这并不比循环更好。它可能更易读(个人偏好)。对于下面所有的答案,请注意你需要导入System.Linq命名空间。它们也返回懒加载的IEnumerable<T>(在迭代时执行)。如果你想返回一个具体的列表,你可以调用.ToList()扩展方法

有没有更好的方式来返回所有键的列表,而不仅仅是在KeyValuePair列表上进行foreach?

KV_List.Select(kvp => kvp.Key);

同样地,有没有比使用foreach更好的方法来返回给定键的所有值列表?
var theKeyToLookFor = "qwer";
KV_List.Where(kvp => kvp.Key == theKeyToLookFor).Select(kvp => kvp.Value);

那么,针对给定的值返回一个键列表怎么样?
var theValueToLookFor = "asdf";
KV_List.Where(kvp => kvp.Value == theValueToLookFor)
       .Select(kvp => kvp.Value)
       .ToList();

想了解更多关于LINQ的信息,请查看LINQ (语言集成查询)


2

你是否正在阅读这篇文章,并想知道为什么有些代码使用IEnumerable<KeyValuePair<A,B>>而不是Dictionary<A,B>,但又不想问,只是想完成任务?

if (collection == null)
    return null;

return collection 
    .Where(z => z.Key == aThing)
    .Select(z => z.Value)
    .FirstOrDefault();

1

1:

KV_List.Select(i => i.Key).ToList()

2:

KV_List.Where(i => i.Key == filterByKey).Select(i => i.Value).ToList()

3:

 KV_List.Where(i => i.Value == filterByValue).Select(i => i.Key).ToList()

1

在您的情况下,我会使用ILookup<K,V>。它类似于字典,但您可以使用相同的键获取IEnumerable<V>的值。

ILookup<string, string> lookup = KV_List.ToLookup(x => x.Key, x => x.Value);
IEnumerable<string> list = lookup["qwer"];
foreach(string str in list)
{
    Console.WriteLine(str);
}

或者简单地说

Console.WriteLine(string.Join(",", lookup["qwer"]));

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