【问题标题】:Dictionary with two keys?字典有两个键?
【发布时间】:2012-02-27 03:46:15
【问题描述】:

我在控制台中跟踪值。两个人互相“决斗”,我用字典来记录名字和造成的伤害。

var duels = new Dictionary<string, string>();
duels.Add("User1", "50");
duels.Add("User2","34");

我正在尝试将两个用户存储在同一个字典行中,因此可以验证 User1 正在与 User2 决斗。这样如果再次决斗开始,它不会干扰User1User2

duels.Add("KeyUser1","KeyUser2","50","34",.../*Other attributes of the duel*/);

我需要两把钥匙,这样我就可以检查用户的损坏情况。损坏总是会转到另一把钥匙上——反之亦然。 我可以做些什么来完成这项工作?

谢谢。

【问题讨论】:

  • 我建议为此使用元组。这是一篇相关文章,可能会引导您朝着正确的方向前进:stackoverflow.com/questions/1171812/multi-key-dictionary-in-c。祝你好运!
  • 一个用户一次可以参与多个决斗吗?
  • “User1”和“User2”的决斗与“User2”和“User1”的决斗有区别吗?
  • @Branko 不,他们不能。@David B 不,一点也不不同。对 2 人的决斗可以互换。
  • Tuple 可能会强制您在一开始就对其进行初始化,但不要在以后对其进行膨胀。

标签: c# dictionary


【解决方案1】:
public class Duel
{
  public string User1 {get; protected set;}
  public string User2 {get; protected set;}
  public Duel(string user1, string user2)
  {
    User1 = user1;
    User2 = user2;
  }

  public HashSet<string> GetUserSet()
  {
    HashSet<string> result = new HashSet<string>();
    result.Add(this.User1);
    result.Add(this.User2);
    return result;
  }

  //TODO ... more impl
}

让我们进行一些决斗。 CreateSetComparer 允许字典使用集合的值进行相等性测试。

List<Duel> duelSource = GetDuels();
Dictionary<HashSet<string>, Duel> duels =
  new Dictionary<HashSet<string>, Duel>(HashSet<string>.CreateSetComparer());

foreach(Duel d in duelSource)
{
  duels.Add(d.GetUserSet(), d);
}

并找到决斗:

HashSet<string> key = new HashSet<string>();
key.Add("User1");
key.Add("User2");
Duel myDuel = duels[key];

【讨论】:

    【解决方案2】:

    快点。

    class UserScores {
    
        public string Key { get; set; }
    
        public int User1Score { get; set; }
        public int User2Score { get; set; }
    
        public UserScores(string username1, string username2)
        {
                Key = username1 + ":" + username2;
        }
    }
    
    void Main()
    {
        var userScore = new UserScores("fooUser", "barUser");
    
        var scores = new Dictionary<string, UserScores>();
    
        scores.Add(userScore.Key, userScore);
    
        // Or use a list
    
        var list = new List<UserScores>();
    
        list.Add(userScore);
    
        list.Single (l => l.Key == userScore.Key);
    }
    

    虽然在我看来一个合适的解决方案会使用一个经过深思熟虑的 UserScores 对象来跟踪特定的“决斗”会话。

    【讨论】:

    • 如果vinyetish 正在打架,而vinyetish 正在打架怎么办? :)
    • 我喜欢将它们组合在一起的想法。我想我可以添加类似username1+":"+username2 的内容,然后拆分: 以获得user[0]user[1]
    • 另外@Kyle 不要忘记添加 GetHashCode() 和 IEquatable.Equals() 实现。
    【解决方案3】:

    您可以尝试为键创建自定义数据类型:

    class DualKey<T> : IEquatable<DualKey<T>> where T : IEquatable<T>
    {
        public T Key0 { get; set; }
        public T Key1 { get; set; }
    
        public DualKey(T key0, T key1)
        {
            Key0 = key0;
            Key1 = key1;
        }
    
        public override int GetHashCode()
        {
            return Key0.GetHashCode() ^ Key1.GetHashCode();
        }
    
        public bool Equals(DualKey<T> obj)
        {
            return (this.Key0.Equals(obj.Key0) && this.Key1.Equals(obj.Key1))
                || (this.Key0.Equals(obj.Key1) && this.Key0.Equals(obj.Key0));
        }
    }
    

    然后使用Dictionary&lt;DualKey&lt;string&gt;, string&gt;;

    【讨论】:

    • 我不想听起来粗鲁,但根据 Stack Overflow 规范,这应该是对原始问题的评论,而不是作为答案提交。不希望你被否决:)
    • 我没有尝试过嵌入式字典。这不是意味着有不同的关键字典吗?
    【解决方案4】:

    由于一个人一次最多可以参与一场决斗,您可以使用单个字典直接“索引”所有决斗中的两个端点,如下所示:

    class Duel {
    
        public Duel(string user1, string user2) {
            Debug.Assert(user1 != user2);
            User1 = user1;
            User2 = user2;
        }
    
        public readonly string User1;
        public readonly string User2;
        public int User1Score;
        public int User2Score;
    
    }
    
    class Program {
    
        static void Main(string[] args) {
    
            var dict = new Dictionary<string, Duel>();
    
            // Add a new duel. A single duel has two keys in the dictionary, one for each "endpoint".
            var duel = new Duel("Jon", "Rob");
            dict.Add(duel.User1, duel);
            dict.Add(duel.User2, duel);
    
            // Find Jon's score, without knowing in advance whether Jon is User1 or User2:
            var jons_duel = dict["Jon"];
            if (jons_duel.User1 == "Jon") {
                // Use jons_duel.User1Score.
            }
            else {
                // Use jons_duel.User2Score.
            }
    
            // You can just as easily find Rob's score:
            var robs_duel = dict["Rob"];
            if (robs_duel.User1 == "Rob") {
                // Use robs_duel.User1Score.
            }
            else {
                // Use robs_duel.User2Score.
            }
    
            // You are unsure whether Nick is currently duelling:
            if (dict.ContainsKey("Nick")) {
                // Yup!
            }
            else {
                // Nope.
            }
    
            // If Jon tries to engage in another duel while still duelling Rob:
            var duel2 = new Duel("Jon", "Nick");
            dict.Add(duel2.User1, duel); // Exception! Jon cannot be engaged in more than 1 duel at a time.
            dict.Add(duel2.User2, duel); // NOTE: If exception happens here instead of above, don't forget remove User1 from the dictionary.
    
            // Removing the duel requires removing both endpoints from the dictionary:
            dict.Remove(jons_duel.User1);
            dict.Remove(jons_duel.User2);
    
            // Etc...
    
        }
    
    }
    

    这只是一个基本的想法,你可以考虑将这个功能包装在你自己的类中......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 2015-12-22
      相关资源
      最近更新 更多