根据键对字典列表进行排序

时间:2015-08-29 10:29:45

标签: c# linq list sorting dictionary

我有一个包含学生数据的词典列表 它就像

List<Dictionary<string, object>> students = new List<Dictionary<string, object>>();
Dictionary<string, object> std1 = new Dictionary<string, object>();
std1["name"] = "sai";
std1["age"] = 22;
std1["gender"] = "male";
students.Add(std1);

Dictionary<string, object> std2 = new Dictionary<string, object>();
std2["name"] = "Julia";
std2["gender"] = "female";
students.Add(std2);

Dictionary<string, object> std3 = new Dictionary<string, object>();
std3 ["name"] = "sunny";
std3 ["age"] = 23;
students.Add(std3);  

我想根据nameagegender对学生列表进行排序,我正在尝试这样的事情:

var ordered = students.OrderBy(x => x["name"]);

如果我尝试使用agegender,则会返回错误,指出找不到密钥,因为std2没有age和{{ 1}}没有std3

我需要所有记录,即使它不包含排序键的值,任何解决此问题的方法,提前谢谢。

3 个答案:

答案 0 :(得分:3)

最好创建一个这样的类:

public class YourClass
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
}

然后:

List<YourClass> students = new List<YourClass>();
YourClass std1 = new YourClass();
std1.Name = "sai";
std1.Age = 22;
std1.Gender = "male";
students.Add(std1);

yourClass std2 = new yourClass();
std2.Name = "Julia";
std2.Gender = "female";
students.Add(std2);

yourClass std3 = new yourClass();
std3.Name = "sunny";
std3.Age = 23;
students.Add(std3);

var ordered = students.OrderBy(x => x.Name);

此安排存储您在多个词典中使用的相同数据。但是,它更加清晰易懂。

答案 1 :(得分:2)

如果要按所有词典中不存在的键排序,则需要返回默认值,例如0。

var ordered = students.OrderBy(dict =>
{
    string name;
    if (!dict.TryGetValue("name", out name))
        return "";
    return name;
});

使用条件三元运算符的较短版本:

var ordered = students.OrderBy(dict =>
{
    string name;
    return dict.TryGetValue("name", out name) ? name : 0;
});

我使用Dictionary.TryGetValue(...)返回一个bool,描述是否在字典中找到了密钥并返回了它的值。

答案 2 :(得分:1)

您可以通过提供GetOptional方法来解决此问题,该方法在字典没有特定键的情况下返回一些默认对象:

V GetOptional<K,V>(IDictionary<K,V> d, K key, V absent) {
    V res;
    return d.TryGetValue(key, out res) ? res : absent;
}

现在你可以这样排序:

var byName = students.OrderBy(x => GetOptional<string,object>(x, "name", "----"));
var byAge = students.OrderBy(x => GetOptional<string,object>(x, "age", "10000"));

注意:使用这样的词典可以提高灵活性,但会牺牲清晰度。通常最好定义一个特殊的Student类型,而不是使用通用的键值对集合。