lucycopp
lucycopp

Reputation: 213

Sorting a dictionary and get top 3

I have a dictionary which stores members of a 'Skiing' tournament. It also stores there scores. What I want to do is be able to find and display the top 3 scores of the members. I was just wondering what the best way would be to approach this as I am stuck at the moment. The following is the dictionary and how a member is added:

public static Dictionary<string, Skier> Skiers = new Dictionary<string, Skier>();

    static int income;


    string lodgeName;

    public SkiLodge(string newLodgeName)
    {
        newLodgeName = lodgeName;
        Skiers = new Dictionary<string, Skier>();
    }

    static int newNumber = 1;
    //ADD SKIER
    public Skier AddSkier(string inName, string inAddress, int inScore)
    {
        string newNumberString = newNumber.ToString();
        Skier result = new Skier(newNumberString, inName, inAddress, inScore);
        newNumber = newNumber + 1;
        Skier S = new Skier(newNumberString, inName, inAddress, inScore);
        Skiers.Add(newNumberString, S);
        income = income + 100;
        return result;
    }

Upvotes: 2

Views: 180

Answers (6)

BenVlodgi
BenVlodgi

Reputation: 2185

Either of these methods added to your SkiLodge class, will get you what you're looking for.

This will grab your top X KeyValuePairs with the Skier object being the Value property of the KeyValuePair.

public List<KeyValuePair<string,Skier>> GetTopSkiers(int howMany)
{
    return Skiers.OrderByDescending(kvp => kvp.Value.Score).Take(howMany).ToList();
}

This will grab your top X Skiers

public List<Skier> GetTopSkiers(int howMany)
{
    return Skiers.OrderByDescending(kvp => kvp.Value.Score).Take(howMany).Select(kvp => kvp.Value).ToList();
}

Both methods use the OrderByDescending Linq method, which uses a lambda expression as a selector for the sorting comparison kvp => kvp.Value.Score. Which in this case is saying, foreach kvp (KeyValuePair) in this dictionary, sort them by the Value property, which in this case is the Skier object, and use the Skier object's Score as the value to sort by.

Take will take, up to x values from an Enumerable.

Select then returns an Enumerable resulting from the lambda function passed in. In this case, kvp => kvp.Value returns an Enumerable of Skier objects, instead of a list of the KeyValuePair objects.

Upvotes: 3

Mukesh Adhvaryu
Mukesh Adhvaryu

Reputation: 646

Using System.Linq, the following code will get you the best 3 Skiers by score:

public List<Skier> GetTop3()
{
var list = Skiers.OrderByDescending(sk=> sk.Value.Score).Take(3).ToList();
return list;
}

Upvotes: 1

Kiran Paul
Kiran Paul

Reputation: 885

You may use LINQ to achieve. Here is one sample query:

Skiers.OrderByDescending(e=>e.Value.inScore).Take(3).ToList();

Upvotes: 1

jdweng
jdweng

Reputation: 34421

Either use a SortedDictionary or enumerate through the keys of dictionary or this code

   public class Skier
    {
        public static Dictionary<string, Skier> Skiers = new Dictionary<string, Skier>();
        public int inScore { get; set; }
        public Skier()
        {
            int[] highscore = Skiers.AsEnumerable().OrderByDescending(x => ((Skier)x.Value).inScore).Take(3).Select(y => ((Skier)y).inScore).ToArray();
        }
    }

Upvotes: 1

Avneesh
Avneesh

Reputation: 654

I have tried to replicate the behavior and fixed some of the issues in above code. In AddSkier you dont need to create 2 objects. FetchTopThree() will give you the top 3 results. You can then display the results.

using System.Collections.Generic;
using System.Linq;


    public class SkiLodge
    {
        public static Dictionary<string, Skier> Skiers = new Dictionary<string, Skier>();

        static int income;

        string lodgeName;

        public SkiLodge(string newLodgeName)
        {
            this.lodgeName = newLodgeName;
        }

        static int newNumber = 1;
        //ADD SKIER
        public Skier AddSkier(string inName, string inAddress, int inScore)
        {
            string newNumberString = newNumber.ToString();
            newNumber = newNumber + 1;
            Skier skier= new Skier(newNumberString, inName, inAddress, inScore);
            Skiers.Add(newNumberString, skier);
            income = income + 100;
            return skier;
        }

        public List<Skier> FetchTopThree()
        {
            return Skiers.Values.OrderByDescending(s => s.InScore).Take(3).ToList();
        }
    }

    public class Skier
    {
        public string NewNumberString { get; }
        public string InName { get; }
        private readonly string inAddress;
        public int InScore { get; }

        public Skier(string newNumberString, string inName, string inAddress, int inScore)
        {
            this.NewNumberString = newNumberString;
            this.InName = inName;
            this.inAddress = inAddress;
            this.InScore = inScore;
        }
    }

Upvotes: 0

Bruno Joaquim
Bruno Joaquim

Reputation: 1473

I assumed that you have a property in Skier called Score, here how can you achieve your goal.

    //Your dictionary must have at least 3 entries.
    var orderedTopThree = Skiers.OrderByDescending(s => s.Value.Score).Take(3);

Upvotes: 7

Related Questions