C#/Linq - 对字典进行排序

Posted

技术标签:

【中文标题】C#/Linq - 对字典进行排序【英文标题】:C#/Linq - Sort IDictionary 【发布时间】: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 您是在寻找真正对字典进行排序还是仅按特定顺序显示它们? 【参考方案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 使用互操作。所以这些方法是存在的,只是没有暴露出来。

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

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 查询应该不会太复杂。

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

【讨论】:

以上是关于C#/Linq - 对字典进行排序的主要内容,如果未能解决你的问题,请参考以下文章

对字典中的数组进行排序[重复]

python怎么对字典进行排序

按字典顺序对c ++中的多维向量进行排序

python(46):对字典进行排序

按特定键的降序对字典列表进行排序[重复]

iPhone Obj C——对一个可变字典数组进行排序——显示一个字符串但按值排序