C#/Linq - Sort IDictionary

本文关键字:Sort IDictionary Linq | 更新日期: 2023-09-27 18:35:15

我正在使用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,但我仍在努力掌握它的工作原理。

一些帮助将不胜感激。谢谢!

C#/Linq - Sort IDictionary

给定:

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();
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]
                    }
                 );

小提琴

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;}
}

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

来自Firebase-talk Google Group的这篇文章:

目前,[Firebase Library for Unity]仅支持完整平台上的功能子集。unity sdk 的工作方式是它对完整的 sdk 使用互操作。 所以这些方法就在那里,只是没有暴露。

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

  • https://github.com/firebase/Firebase-Unity/blob/master/empty-project/Assets/Plugins/Android/QueryAndroidImpl.cs

  • https://github.com/firebase/Firebase-Unity/blob/master/empty-project/Assets/Plugins/iOS/QueryiOSImpl.cs

  • https://github.com/firebase/Firebase-Unity/blob/master/empty-project/Assets/Plugins/iOS/Firebase.mm

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

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

这个话题仍然很新鲜,所以如果你有其他问题,我建议你在那里发布。