【问题标题】:C#/Linq - Sort IDictionaryC#/Linq - 对字典进行排序
【发布时间】:2016-05-30 11:18:14
【问题描述】:

我正在使用 Firebase for Unity 来存储一些带有分数的用户。 Firebase 将我的用户列表返回为 IDictionary<string, object>,其中 Key 是 Firebase 生成的某个 id,Value 是另一个代表用户的 IDictionary<string, object>

用户有一个名为“分数”的Key,我想按照排行榜分数的Value 对所有用户进行排序。

这或多或少的数据看起来像 JSON:

"users": {
  "<userid>" : {
    "name" : "John",
    "score": 5
    ...  
  },
  "<userid>" : {
    "name" : "Pete",
    "score" : 10
  }
  ... 
}

我将如何对用户列表进行排序?我认为我需要以某种方式使用 Linq,但我仍在努力掌握它的工作原理。

我们将不胜感激。 谢谢!

【问题讨论】:

  • 您无法对IDictionary&lt;K, V&gt; 进行排序。它们没有定义的排序顺序。这就是SortedDictionary 存在的原因。除非你很高兴拥有IEnumerable&lt;KeyValuePair&lt;string, object&gt;&gt;,否则你无法得到你想要的。
  • Dictionary 无法排序,请改用List
  • this
  • 您是在寻找真正对字典进行排序还是仅按特定顺序显示它们?

标签: c# linq unity3d firebase


【解决方案1】:

给定:

IDictionary<string, object> dict = new Dictionary<string, object>() {
    { "1", new Dictionary<string, object>() 
        {
            { "name", "John" },
            { "score", 5 }
        }
    },
    { "2", new Dictionary<string, object>() 
        {
            { "name", "Pete" },
            { "score", 4 }
        }
    },
};

你可以:

var ordered = dict.OrderBy(x => (int)((IDictionary<string, object>)x.Value)["score"]).ToArray();

这很丑陋,如果score 丢失,那么你会得到一个异常。

如果score 可能丢失:

public static TValue GetValueOrDefault<TKey, TValue>(IDictionary<TKey, TValue> dict, TKey key)
{
    TValue value;
    dict.TryGetValue(key, out value);
    return value;
}

然后

var ordered = dict.OrderBy(x => (int?)GetValueOrDefault((IDictionary<string, object>)x.Value, "score")).ToArray();

【讨论】:

    【解决方案2】:
    const string scoreKey = "score";
    const string nameKey = "name";
    var highscores = userDict
                    .OrderByDescending(u => ((IDictionary<string, object>)u.Value)[scoreKey])
                    .Select(u => new {
                            Name = ((IDictionary<string, object>)u.Value)[nameKey], 
                            Score = ((IDictionary<string, object>)u.Value)[scoreKey]
                        }
                     );
    

    Fiddle

    【讨论】:

      【解决方案3】:
      IEnumerable<User> OrderByScore(IDictionary<string,object> firebaseList)
      {
          return from user in firebaseList.Values.Cast<IDictionary<string,object>>()
              let name  = (string) user["name"]
              let score = int.Parse(user["score"].ToString())
              orderby score descending
              select new User { Name = name, Score = score};
      }
      
      class User
      {
          public string Name  {get;set;}
          public int    Score {get;set;}
      }
      

      【讨论】:

        【解决方案4】:

        其他 cmets 和答案侧重于过滤用户客户端。这个答案是关于使用 Firebase 的内置查询功能来过滤服务器上的数据,遗憾的是 Unity 库中尚不提供该功能。

        来自post on the firebase-talk Google Group

        目前,[Firebase for Unity 库] 仅支持您在完整平台上可以找到的部分功能。 unity sdk 的工作方式是它对完整的 sdk 使用互操作。所以这些方法是存在的,只是没有暴露出来。

        我们接受拉取请求。 [如果您有兴趣贡献],请查看:

        它可能会给你足够的想法来添加额外的方法。

        支持桌面播放器(能够点击播放)有点复杂,但启用 iOS 和 Android 查询应该不会太复杂。

        这个话题还是很新鲜的,所以如果您还有其他问题,我建议您在那里发布。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-05-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多