【问题标题】:Dictionary with two keys带两个键的字典
【发布时间】:2012-09-05 13:18:06
【问题描述】:

通过字典中的两个键索引值的最佳方法是什么。例如:让具有唯一 ID(整数)和用户名(字符串)的学生创建一个字典,其中包含由 ID 和用户名索引的学生类型对象。然后在检索时使用 ID 或用户名。 或者可能是字典不是一个很好的匹配? 附言我知道元组,但看不到如何在这种情况下使用它们。

编辑:作为使用两个键的替代方法,我可以创建由唯一分隔符分隔的 id 和用户名的字符串表示,然后使用正则表达式匹配键?!例如:“1625|user1”

【问题讨论】:

  • 用户名是否也是唯一的?
  • Dictionary<string,Dictionary<int,Student>> 该类型的属性应该可以根据需要工作
  • 是的,在“unique Id(integer) and username(string)”中是唯一的
  • 如果您接受@harry180 的评论,我建议您创建一个新类来抽象这种复杂性。我以前见过他们失控,比如Dictionary<string, Dictionary<string, List<Dictionary<int,string>>>。它只是使它更易于维护,您可以在不影响现有代码的情况下进行切换
  • @Dimitri:所以 ID (int) 在学生之间不是唯一的吗?

标签: c# dictionary


【解决方案1】:

由于您希望能够通过其中任何一个检索,因此您需要两个字典。

假设Student 类型是一个引用类型,那么每个学生仍然只有一个Student 对象,所以不用担心。

最好将字典包装在一个对象中:

public class StudentDictionary
{
  private readonly Dictionary<int, Student> _byId = new Dictionary<int, Student>();
  private readonly Dictionary<string, Student> _byUsername = new Dictionary<string, Student>();//use appropriate `IEqualityComparer<string>` if you want other than ordinal string match
  public void Add(Student student)
  {
    _byId[student.ID] = student;
    _byUsername[student.Username] = student;
  }
  public bool TryGetValue(int id, out Student student)
  {
    return _byId.TryGetValue(id, out student);
  }
  public bool TryGetValue(string username, out Student student)
  {
    return _byUsername.TryGetValue(username, out student);
  }
}

等等。

【讨论】:

  • 太棒了。看起来像我的答案
  • 可以构建一个更轻量的双键字典,但很难证明付出的大量额外努力是合理的。
  • 是的,我看到这绝对对我有用,并且足以满足我的需求。非常感谢
  • 您想像这样向您的班级介绍“索引器”:public Student this[int id] { get { return _byId[id]; } }public Student this[string username] { get { return _byUsername[username]; } }。因为它很酷。它们的使用方式如下:studDict[1336654]studDict["jeppesn"] 其中studDict 是一些StudentDictionary 对象。
  • ... 3. 做不到这一点,我会构建自己的低锁线程安全字典,但对于我之前构建过低锁线程安全字典的人来说,这更容易说.我不想在截止日期前完成!
【解决方案2】:

您可以使用两个保持同步的字典,一个将姓名映射到学生,另一个将 ID 映射到学生。最简单的方法可能是将其包装在您自己的处理同步的类中。

【讨论】:

    【解决方案3】:

    不,只有当您始终同时拥有 IdUsername 时,Tuple 才会对您有所帮助。您可以为每个键使用Dictionaries。您还可以实现自己的Dictionary,这使您能够查询这两个键,因为它们的类型不同:

    class MyDictionary : IDictionary<int, Student>, IDictionary<string, Student> {
        // full implementation
    }
    

    【讨论】:

    • 我如何检查一个键是否在字典中? MyDictionary.Keys.Contains(178) || MyDictionary.Keys.Contains("User2") ?
    • Jon 提出了一个简洁的实现。 MyDictionary 有责任保持两个内部词典同步(因此它们都包含相同的一组学生),因此您只需检查 178User2
    • 是的,非常感谢。赞成您对优雅方法的回答
    【解决方案4】:

    使用 student 对象是您想要的一个不错的选择,但您必须重写相等函数(Equals 和 GetHashCode)才能使其正常工作。

    在仔细阅读这部分后进行编辑“然后在检索时使用 ID 或用户名”我认为我的回答不是最好的方法。我会带两本字典,所以 +1 给@JonHanna。

    【讨论】:

    • 你介意扩展这个答案吗?我看不出GetHashCode与任何事情有什么关系。
    • 我没有使用学生对象作为键,只是值
    • 只是为了澄清 GetHashCode,在没有匹配的自定义 GetHashCode 的情况下实现自定义 Equals 总是一个坏主意,因为有时哈希码用于测试是否相等。这可能是 Java 编码的“交叉污染”,但我认为它仍然适用于一个很好的一般规则。
    • 经过进一步研究发现,c# 中的字典(就像所有其他哈希表实现一样)使用哈希码进行内部索引和检索。
    • 在 gethashcode 上为真。顺便说一句,我在回答中提到了IEqualityComparer&lt;string&gt;。这为自定义目的提供了自定义 equals 和 gethashcode(.NET 提供了几个开箱即用的字符串相关案例)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    • 2014-03-03
    • 2018-03-10
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多