Matey Johnson
Matey Johnson

Reputation: 227

OrderBy in List on the basis of Dictionary Key-Value

I have the following List:

List<Student> list = 
[
  {
    "id": 1,
    "name": "Student 1",
    "OtherInformation": {
      "hobby": "Music",
      "Score": 50
    }
  },
  {
    "id": 2,
    "name": "Student 2",
    "OtherInformation": {
      "hobby": "Golf",
      "Score": 70
    }
  },
  {
    "id": 3,
    "name": "Student 3",
    "OtherInformation": {
      "hobby": "Archery",
      "Score": 30
    }
  }
]

Other Information is a Dictionary and I need to OrderBy the complete list using the dictionary Value which will be dynamic i.e. stored in some variable.

var sortKey = "id";
var propertyInfo = typeof(Student).GetProperty(sortKey);
list = list.OrderBy(x => propertyInfo.GetValue(x, null)).ToList();

I'm not able to do the above solution for Dictionary Key-Values such as Score

Student.cs

 public class Student
{
 public string Id {get;set;}
 public string Name {get;set;}
 public IDictionary<string, object> OtherInfomration{get;set;}
}

Help needed.

Upvotes: 0

Views: 104

Answers (3)

Samy Sammour
Samy Sammour

Reputation: 2465

I made a mini console application using this data:

 class Program
 {
     static void Main(string[] args)
     {
         List<Student> list = new List<Student>()
            {
             new Student() { Id = 1, Name = "Student 1", OtherInformation = new Dictionary<string, string>()
                                         {
                                             { "hobby", "Music" },
                                             { "Score",  "50" }
                                         }
                                     },
             new Student() { Id = 2, Name = "Student 2", OtherInformation = new Dictionary<string, string>()
                                         {
                                             { "hobby", "Golf" },
                                             { "Score",  "70" }
                                         }
                                     },
             new Student() { Id = 3, Name = "Student 3", OtherInformation = new Dictionary<string, string>()
                                         {
                                             { "hobby", "Archery" },
                                             { "Score",  "30" }
                                         }
                                     }
         };

         Console.WriteLine(list.OrderBy(x => x.OtherInformation["Score"]).FirstOrDefault().Name);
         Console.Read();
      }
 }

The result was Student 3 as wanted because he has the lowest score.

EDIT:

Here you can use a pre-defined order statments:

public class OrderByStatment
{
    private string propertyName;

    public OrderByStatment(string propertyName)
    {
        this.propertyName = propertyName;
    }

    public Expression<Func<Student, object>> GetOrderBy()
    {
        switch (this.propertyName)
        {
            case "id": return s => s.Id;
            case "name": return s => s.Name;
            case "score": return s => s.OtherInformation["Score"];
            case "hobby": return s => s.OtherInformation["hobby"];
            default: return s => s.Id;
        }
    }
}

calling it will be then:

Console.WriteLine(list.OrderBy(new OrderByStatment("id").GetOrderBy().Compile()).FirstOrDefault().Name);
Console.WriteLine(list.OrderBy(new OrderByStatment("score").GetOrderBy().Compile()).FirstOrDefault().Name);

You can absolutely make the code better by defining inheritance. Instead of new OrderByStatment("[propertyName]") you can use new IdOrderBy()

Hope that answers your question

Upvotes: 0

Tim Rutter
Tim Rutter

Reputation: 4679

I think you want to do this:

var sortKey = "OtherInformation";
var propertyInfo = typeof(Student).GetProperty(sortKey);
list = list.OrderBy(x => ((IDictionary<string, object>)propertyInfo.GetValue(x, null))["Score"]).ToList();

Its not entirely clear why you're using reflection however. You could easily just do this:

list = list.OrderBy(x => x.OtherInformation["Score"]).ToList();

Upvotes: 2

Gauravsa
Gauravsa

Reputation: 6524

You can do this:

var sorted = list.OrderBy(x => Convert.ToInt32(x.OtherInformation["Score"]));

Convert.ToInt32 is a bit dodgy as it can throw an exception.

Upvotes: 0

Related Questions