如何在 C# 字典中将一个值分配给多个键?

5
我想定义一个字母表的字典。在这个字典中,字符是键,而每个键都有一个相应的值。 我已经用最简单的方法写出来了,你可以看到一些键具有相同的值。
var testDict = 
        new Dictionary <char, int>() { 
            {'A', 1}, {'E', 1}, {'I', 1}, 
            {'O', 1}, {'U', 1}, {'L', 1}, 
            {'N', 1}, {'R', 1}, {'S', 1}, 
            {'T', 1}, 
            {'D', 2}, {'G', 2},
            {'B', 3}, {'C', 3}, {'M', 3}, {'P', 3}, 
            {'F', 4}, {'H', 4}, {'V', 4}, {'W', 4}, {'Y', 4}, 
            {'K', 5}, 
            {'J', 8}, {'X', 8}, 
            {'Q',10}, {'Z',10}};

我需要找出其中的字母并使用分配的值,如何更加简洁地写出来?


从技术上讲,您的做法是正确的,但一切取决于您如何使用字典。您需要通过字母来查找一个值吗?还是您想通过整数值找到所有字母?或者您可能需要其他功能,请详细说明您希望如何使用该字典。 - E. Shcherbo
是的,我想要搜索一个字母并使用它的指定值。因此,我将字母视为键。@E.Shcherbo - elldora
1
那么,如果您对自己的解决方案感到满意,就可以继续使用它,但是如果您担心代码的清晰度,可以查看@Charlieface的答案,但我个人认为这会更加混乱,而不是有所帮助。 - E. Shcherbo
1
你也可以创建一个空字典,然后编写一个方法,该方法接受一个键列表和一个要映射键的值。在该方法中,您只需为每个键添加映射到值的映射即可。void MapValueToKeys(Dictionary<char, int> values, IEnumerable<char> keys, int value) - E. Shcherbo
要明确的是,每个键具有相同的值并不是问题(当然取决于领域),可以想象电话簿,其中电话号码映射到人名。拥有两个不同号码但姓名相同的人是可以接受的。 - E. Shcherbo
3个回答

4
一个 Dictionary<TKey, TValue> 是由键值对组成的集合。在这个集合中,每个键只映射一个值。它被实现在 System.Collection.Generics 命名空间中。
另一方面,有一个集合名为Lookup<TKey, TElement>,它表示键和值之间的一对多映射。即它将一个键映射到一个或多个值,并且它在 System.Linq 命名空间中。
您可以将任何已实现IEnumerable 接口和 System.Linq 命名空间中的 ToLookup() 方法的集合转换为 Lookup<TKey, TElement> 集合。
在 Microsoft 的 C# 语言教程中了解更多关于 Lookup 集合和 Dictionary 的内容。
在这个问题中,我们可以考虑一个由两个字段组成的包,即“字母”字符及其在一个句子中出现的“计数”。
class Package
{
    public char Alphabet;
    public int Counts;
}

然后构建查找数据结构:

public static void LookupExample()
{
    // Create a dictionary of Packages to put into a Lookup data structure.
    var testDict = new Dictionary <char, int>() { 
         new Package { Alphabet = 'A', Counts = 1},
         new Package { Alphabet = 'B', Counts = 3},
         new Package { Alphabet = 'C', Counts = 3},
         new Package { Alphabet = 'D', Counts = 2},
         new Package { Alphabet = 'E', Counts = 1},
         new Package { Alphabet = 'F', Counts = 4},
         new Package { Alphabet = 'G', Counts = 2},
         new Package { Alphabet = 'H', Counts = 4},
         new Package { Alphabet = 'I', Counts = 1},
         new Package { Alphabet = 'J', Counts = 8},
         new Package { Alphabet = 'K', Counts = 5},
         new Package { Alphabet = 'L', Counts = 1},
         new Package { Alphabet = 'M', Counts = 3},
         new Package { Alphabet = 'N', Counts = 1},
         new Package { Alphabet = 'O', Counts = 1},
         new Package { Alphabet = 'P', Counts = 3},
         new Package { Alphabet = 'Q', Counts = 10},
         new Package { Alphabet = 'R', Counts = 1},
         new Package { Alphabet = 'S', Counts = 1},
         new Package { Alphabet = 'T', Counts = 1},
         new Package { Alphabet = 'U', Counts = 1},
         new Package { Alphabet = 'V', Counts = 4},
         new Package { Alphabet = 'W', Counts = 4},
         new Package { Alphabet = 'X', Counts = 8},
         new Package { Alphabet = 'Y', Counts = 4},
         new Package { Alphabet = 'Z', Counts = 10}};
                                                         

    // Create a Lookup to organize the packages. Use the Counts of each Alphabet as the key value.
    // Select Alpahbet appended to each Counts in the Lookup.
    Lookup<int, char> lookup = (Lookup<int, char>)testDict.ToLookup(p => p.Counts, p => p.Alphabet);

    // Iterate through each IGrouping in the Lookup and output the contents.
    foreach (IGrouping<int, char> packageGroup in lookup)
    {
        // Print the key value of the IGrouping.
        Console.WriteLine(packageGroup.Key);
        // Iterate through each value in the IGrouping and print its value.
        foreach (char chr in packageGroup)
            Console.WriteLine("    {0}", Convert.ToString(chr));
    }
 }

这有助于将“计数”视为新的关键字,并为具有相同“计数”值的多个“字母表”字符分配它!

这也是一篇有价值的帖子,讨论了ToDictionary和ToLookup方法之间的区别。https://dev59.com/c2035IYBdhLWcg3wC7cR - elldora

1
使用这个扩展方法:
    public static void Add<TKey, TValue>(this Dictionary<TKey, TValue> dict, TValue value, params TKey[] keys)
    {
        foreach (var key in keys)
            dict.Add(key, value);
    }

你可以像这样创建一个字典:

    var testDict =
        new Dictionary<char, int>() {
                {1, 'A', 'E', 'I'},
                {2, 'D', 'G'},
                {3, 'B', 'C', 'M', 'P'},
        };

0
你可以创建一个值到键的字典。 然后,你可以使用linq将其转换为字典:
var tempDict = new Dictionary<int, List<char>>
{
    {1, new List<char> {'A', 'E','I'}},
    {2, new List<char> {'D','G'}}
};
var finalDict = new Dictionary<char, int>();
tempDict.ForEach(x => x.Value.ForEach(y => finalDict[y] = x.Key));

我认为在这里使用列表而不是数组没有任何好的理由。 - canton7
正确的做法是将其转换为 var finalDict = new Dictionary<char, int>();,然后使用 tempDict.ForEach(x => x.Value.ForEach(y => finalDict[y] = x.Key)); 进行赋值。 - Alex S
你本可以在那里使用 SelectMany - canton7

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