获取通用字典指定值的多个键?

获取通用字典指定值的多个键?

很容易从.NET通用字典中获得键的值:

Dictionary<int, string> greek = new Dictionary<int, string>();greek.Add(1, "Alpha");greek.Add(2, "Beta");string secondGreek = greek[2];  // Beta

但是,尝试获取给定值的键并不是那么简单,因为可能有多个键:

int[] betaKeys = greek.WhatDoIPutHere("Beta");  // expecting single 2


炎炎设计
浏览 618回答 3
3回答

慕仙森

好的,这是多个双向版本:using&nbsp;System;using&nbsp;System.Collections.Generic;using&nbsp;System.Text;class&nbsp;BiDictionary<TFirst,&nbsp;TSecond>{ &nbsp;&nbsp;&nbsp;&nbsp;IDictionary<TFirst,&nbsp;IList<TSecond>>&nbsp;firstToSecond&nbsp;=&nbsp;new&nbsp;Dictionary<TFirst,&nbsp;IList<TSecond>>(); &nbsp;&nbsp;&nbsp;&nbsp;IDictionary<TSecond,&nbsp;IList<TFirst>>&nbsp;secondToFirst&nbsp;=&nbsp;new&nbsp;Dictionary<TSecond,&nbsp;IList<TFirst>>(); &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;IList<TFirst>&nbsp;EmptyFirstList&nbsp;=&nbsp;new&nbsp;TFirst[0]; &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;IList<TSecond>&nbsp;EmptySecondList&nbsp;=&nbsp;new&nbsp;TSecond[0]; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;Add(TFirst&nbsp;first,&nbsp;TSecond&nbsp;second) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IList<TFirst>&nbsp;firsts; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IList<TSecond>&nbsp;seconds; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!firstToSecond.TryGetValue(first,&nbsp;out&nbsp;seconds)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seconds&nbsp;=&nbsp;new&nbsp;List<TSecond>(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;firstToSecond[first]&nbsp;=&nbsp;seconds; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!secondToFirst.TryGetValue(second,&nbsp;out&nbsp;firsts)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;firsts&nbsp;=&nbsp;new&nbsp;List<TFirst>(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;secondToFirst[second]&nbsp;=&nbsp;firsts; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seconds.Add(second); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;firsts.Add(first); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Note&nbsp;potential&nbsp;ambiguity&nbsp;using&nbsp;indexers&nbsp;(e.g.&nbsp;mapping&nbsp;from&nbsp;int&nbsp;to&nbsp;int) &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Hence&nbsp;the&nbsp;methods&nbsp;as&nbsp;well... &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;IList<TSecond>&nbsp;this[TFirst&nbsp;first] &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get&nbsp;{&nbsp;return&nbsp;GetByFirst(first);&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;IList<TFirst>&nbsp;this[TSecond&nbsp;second] &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get&nbsp;{&nbsp;return&nbsp;GetBySecond(second);&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;IList<TSecond>&nbsp;GetByFirst(TFirst&nbsp;first) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IList<TSecond>&nbsp;list; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!firstToSecond.TryGetValue(first,&nbsp;out&nbsp;list)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;EmptySecondList; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;List<TSecond>(list);&nbsp;//&nbsp;Create&nbsp;a&nbsp;copy&nbsp;for&nbsp;sanity &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;IList<TFirst>&nbsp;GetBySecond(TSecond&nbsp;second) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IList<TFirst>&nbsp;list; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!secondToFirst.TryGetValue(second,&nbsp;out&nbsp;list)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;EmptyFirstList; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;List<TFirst>(list);&nbsp;//&nbsp;Create&nbsp;a&nbsp;copy&nbsp;for&nbsp;sanity &nbsp;&nbsp;&nbsp;&nbsp;}}class&nbsp;Test{ &nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;void&nbsp;Main() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BiDictionary<int,&nbsp;string>&nbsp;greek&nbsp;=&nbsp;new&nbsp;BiDictionary<int,&nbsp;string>(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;greek.Add(1,&nbsp;"Alpha"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;greek.Add(2,&nbsp;"Beta"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;greek.Add(5,&nbsp;"Beta"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowEntries(greek,&nbsp;"Alpha"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowEntries(greek,&nbsp;"Beta"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowEntries(greek,&nbsp;"Gamma"); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;void&nbsp;ShowEntries(BiDictionary<int,&nbsp;string>&nbsp;dict,&nbsp;string&nbsp;key) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IList<int>&nbsp;values&nbsp;=&nbsp;dict[key]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder&nbsp;builder&nbsp;=&nbsp;new&nbsp;StringBuilder(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(int&nbsp;value&nbsp;in&nbsp;values) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(builder.Length&nbsp;!=&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;builder.Append(",&nbsp;"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;builder.Append(value); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("{0}:&nbsp;[{1}]",&nbsp;key,&nbsp;builder); &nbsp;&nbsp;&nbsp;&nbsp;}}

白衣非少年

正如其他人所说,字典中没有从值到键的映射。我刚刚注意到您想要从Value映射到多个键-我把这个解决方案留给单个值版本,但是接下来我将为多条目双向映射添加另一个答案。这里通常采用的方法是有两本字典-一种是映射方式,另一种是映射方式。将它们封装在一个单独的类中,并计算出当您拥有重复的键或值时要做什么(例如抛出异常、覆盖现有条目或忽略新条目)。就我个人而言,我可能会选择抛出一个例外-它使成功行为更容易定义。就像这样:using&nbsp;System;using&nbsp;System.Collections.Generic;class&nbsp;BiDictionary<TFirst,&nbsp;TSecond>{ &nbsp;&nbsp;&nbsp;&nbsp;IDictionary<TFirst,&nbsp;TSecond>&nbsp;firstToSecond&nbsp;=&nbsp;new&nbsp;Dictionary<TFirst,&nbsp;TSecond>(); &nbsp;&nbsp;&nbsp;&nbsp;IDictionary<TSecond,&nbsp;TFirst>&nbsp;secondToFirst&nbsp;=&nbsp;new&nbsp;Dictionary<TSecond,&nbsp;TFirst>(); &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;Add(TFirst&nbsp;first,&nbsp;TSecond&nbsp;second) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(firstToSecond.ContainsKey(first)&nbsp;|| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;secondToFirst.ContainsKey(second)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentException("Duplicate&nbsp;first&nbsp;or&nbsp;second"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;firstToSecond.Add(first,&nbsp;second); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;secondToFirst.Add(second,&nbsp;first); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;bool&nbsp;TryGetByFirst(TFirst&nbsp;first,&nbsp;out&nbsp;TSecond&nbsp;second) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;firstToSecond.TryGetValue(first,&nbsp;out&nbsp;second); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;bool&nbsp;TryGetBySecond(TSecond&nbsp;second,&nbsp;out&nbsp;TFirst&nbsp;first) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;secondToFirst.TryGetValue(second,&nbsp;out&nbsp;first); &nbsp;&nbsp;&nbsp;&nbsp;}}class&nbsp;Test{ &nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;void&nbsp;Main() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BiDictionary<int,&nbsp;string>&nbsp;greek&nbsp;=&nbsp;new&nbsp;BiDictionary<int,&nbsp;string>(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;greek.Add(1,&nbsp;"Alpha"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;greek.Add(2,&nbsp;"Beta"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;x; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;greek.TryGetBySecond("Beta",&nbsp;out&nbsp;x); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(x); &nbsp;&nbsp;&nbsp;&nbsp;}}

MM们

字典并不是真正像这样工作的,因为虽然键的唯一性得到了保证,但是值的唯一性却不是这样的。var&nbsp;greek&nbsp;=&nbsp;new&nbsp;Dictionary<int,&nbsp;string>&nbsp;{&nbsp;{&nbsp;1,&nbsp;"Alpha"&nbsp;},&nbsp;{&nbsp;2,&nbsp;"Alpha"&nbsp;}&nbsp;};你希望得到什么greek.WhatDoIPutHere("Alpha")?因此,您不能期望将这样的内容滚到框架中。您需要自己的方法来实现自己的独特用途-您想返回一个数组(或IEnumerable<T>)?如果存在具有给定值的多个键,是否要抛出异常?如果没有呢?就我个人而言,我会选择一个可列举的,如下所示:IEnumerable<TKey>&nbsp;KeysFromValue<TKey,&nbsp;TValue>(this&nbsp;Dictionary<TKey,&nbsp;TValue>&nbsp;dict,&nbsp;TValue&nbsp;val){ &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(dict&nbsp;==&nbsp;null) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentNullException("dict"); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;dict.Keys.Where(k&nbsp;=>&nbsp;dict[k]&nbsp;==&nbsp;val);}var&nbsp;keys&nbsp;=&nbsp;greek.KeysFromValue("Beta"); &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;exceptionIfNotExactlyOne&nbsp;=&nbsp;greek.KeysFromValue("Beta").Single();
打开App,查看更多内容
随时随地看视频慕课网APP