【问题标题】:Create a Dictionary with multiple keys and get value using one of keys创建具有多个键的字典并使用其中一个键获取值
【发布时间】:2021-03-04 17:38:42
【问题描述】:

我想创建一个具有多个键的Dictionary,并且当我想仅使用一个或多个键来获得价值时。

我试过了:

        Dictionary<Tuple<int, string>, string> dictionary = new Dictionary<Tuple<int, string>, string>();

        var Key   =new Tuple<int,string>(1,"I1");
        var Value = "this is a value";

        dictionary.Add(Key, Value);

当我尝试从dictionary 获取价值时我必须/应该输入所有键

像这样:

MessageBox.Show($"{dictionary[new Tuple<int, string>(1,"I1")]}");

但是当我尝试只使用这样的一个键来获得价值时

MessageBox.Show($"{dictionary[new Tuple<int, string>(1,"")]}");

我收到错误,我知道这个错误是因为dictionary 需要完整的存在键才能返回一个值。

所以请任何人对我如何创建具有多个keys 的Dictionary 以及在检索值时仅使用一个或更多或有任何想法全部 keys ?

【问题讨论】:

  • 这里的问题可能是数据的冗余吗?先生,你怎么看?
  • 我会在我写的答案中解决这个问题。
  • 我正在等待先生,非常感谢,非常感谢
  • 您可能会遇到这样一个问题:您提供的密钥可以获得多个值
  • @MohamedMoselhy 我确定所有键都没有重复

标签: c# dictionary data-structures collections


【解决方案1】:

.NET 中的字典预计有接近 O(1) 的查找时间。为了实现这一点,他们利用了关键对象的GetHashCode() 和Equals() 方法。生成的哈希码用于将字典的内容划分为分区。当您查找一个项目时,使用哈希码标识分区,该分区中具有匹配哈希码*的所有项目都会与您使用 Equals() 方法查找的键进行比较。

在这里,您尝试为每个对象创建一个包含两个键的字典。您正在使用Tuple 来制作一把钥匙。 Tuple 的 GetHashCode() 结果基于它的两个值,因此如果您只想通过键的一半查找值,字典的性能就会丢失。您需要遍历整个字典,比较每个单独的项目,使其比列表好一点。

一种解决方案是创建一个具有 string->int 键查找的字典,然后另一个字典只是 int->string。这在使用字符串键时需要两次查找,但可能是一个很好的解决方案。

例子:

Dictionary<string, int> stringKeyToIntKey = new Dictionary<string, int>();
Dictionary<int, string> intKeyDict = new Dictionary<int, string>();

intKeyDict[1] = "Test";
stringKeyToIntKey["I1"] = 1;

Console.WriteLine(intKeyDict[1]);
Console.WriteLine(intKeyDict[stringKeyToIntKey["I1"]]);

添加方法可能如下所示:

public void AddEntry(int intKey, string stringKey, string value)
{
    intKeyDict[intKey] = value;
    stringKeyToIntKey[stringKey] = intKey;
}

你可以包装 TryGetValue 让生活更轻松:

public bool TryGetValue(string stringKey, out string value)
{
    value = null;
    return stringKeyToIntKey.TryGetValue(stringKey, out int intKey) && intKeyDict.TryGetValue(intKey, out value);
}

删除看起来像这样:

public void DeleteEntry(string stringKey)
{
    if (stringKeyToIntKey.TryGetValue(stringKey, out int intKey))
    {
        intKeyDict.Remove(intKey);
        stringKeyToIntKey.Remove(stringKey);
    }
}

您必须确保同时从两个词典中添加和删除项目。当您向intKey 添加项目时,您需要将相应的键映射添加到stringKeyToIntKey。

或者,您可以有两个字典:一个带有字符串键,另一个带有 int 键,并且每个字典都具有相同的值。同样,您必须同时添加和删除项目,并且还必须同时更新两者中的值。

例子:

Dictionary<string, string> stringKeyDict = new Dictionary<string, string>();
Dictionary<int, string> intKeyDict = new Dictionary<int, string>();

stringKeyDict["I1"] = "hello";
intKeyDict[1] = "hello";

Console.WriteLine(stringKeyDict["I1"]);
Console.WriteLine(intKeyDict[1]);

这是我最喜欢的方法,其中值是类实例,因为两个字典将为我的项目引用相同的类实例,因此对这些实例属性的更改将反映在两者中。但是,对于字符串,第一个选项可能更好。

* 哈希码不是唯一的,多个对象可能具有相同的哈希码,即使它们的值不同

【讨论】:

  • 真的很感谢您John,让我非常感谢您的时间和精力以及您的出色回答,但请先生,我还有一件事要完成我的理解是,如果我所有的键都是字符串? 你有什么想法来解决这个问题,再次感谢
  • @XDev 如果您所有的键都是字符串,也许您可​​以简单地按照 TaW 的建议进行操作,并将两个条目(每个键一个)添加到每个值的同一个字典中。与我的第二个建议相同的要求将适用,因为您仍将处理两个条目,但如果您没有任何密钥冲突,它应该可以工作。
  • @John 请接受我所有的尊重,非常感谢您的帮助先生
【解决方案2】:

您可以使用字符串作为字典键。假设您想从 int x = 5 和 string y = "str". 创建一个密钥,您可以用一些分隔符连接和拆分它们,然后创建一个这样的密钥:

string key = $"{x}:{y}"

假设您只想通过 x 获取元素。你可以这样写:

dictionary.Where(kvp=>kvp.Key.Contains($"{x}:"))

当然,它不会在 O(1) 时间内提供元素(它会在 O(n) 时间内为您提供元素),但它会起作用。如果您只想通过 x 在 O(1) 时间内获取元素,我不确定是否可以使用一本字典。

【讨论】:

  • 字典不是这样工作的:rextester.com/QOGOF44313
  • 我已经更新了我的问题。谢谢,约翰纠正我的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
  • 2017-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多