Home > Blockchain >  How can I replicate this code by using anonymous function (lambda)?
How can I replicate this code by using anonymous function (lambda)?

Time:12-20

I have a nested dictionary which looks like this:

Dictionary<string, Dictionary<string, int>> users = new Dictionary<string, Dictionary<string, int>>();

The first string is the name of the user, the second is the contest he is taking part in and the int is his score. One user can take part in multiple contests.

My task is to find the user with the highest score by adding all the points he has. For now I used this code :

foreach (var user in users)
{
    bestUsers.Add(user.Key, 0);
    foreach (var contest in user.Value)
    {
        bestUsers[user.Key]  = contest.Value;
    }
}

I want to know how to do it by using anonymous function looking something like this :

KeyValuePair<string, int> bestUser = users.OrderBy(x => x.Value.Sum());

CodePudding user response:

Instead of a nested dictionary, you can create a class that represents the results of the User:

public class UserGameResults
{
    public string Name { get; set; } // the name of the user
    public int TotalScore { get => GameResults.Select(x => x.Value).Sum(); } // total score of all games, will be calculated every time the property is accessed
    public Dictionary<string,int> GameResults { get; set; } = new Dictionary<string,int>(); // key is the name of the game, value is the score
}

If you use a Dictionary<string,UserGameResults>, you will get your result more easily:

var bestResult = users.OrderByDescending(x => x.Value.TotalScore).FirstOrDefault();

Moreover, a Dictionary<string,UserGameResults>tells you much more about the meaning of the data than the Dictionary<string,Dictionary<string,int>>.

CodePudding user response:

For the code refactor to use linq to get the dictionary instead of the 2 foreach loops, you could use something like this:

users.ToDictionary(u => u.Key, u => u.Value.Select(c => c.Value).Sum());

OR i think Sum took an selector lambda

users.ToDictionary(u => u.Key, u => u.Value.Sum(c => c.Value));

Should be valid

CodePudding user response:

try this

var dict = new Dictionary<string, Dictionary<string, int>> {

            { "name1",  new Dictionary<string, int>{ { "A", 2 }, {"B", 3 }}},
            { "name2",  new Dictionary<string, int>{ { "C", 4 }, {"D", 5 }}}
    };

var scores = dict.Select(d => new { name = d.Key, score = d.Value.Select(x => x.Value).Sum() } )
.ToList().OrderByDescending (d =>d.score );

scores

    name2   9
    name1   5

CodePudding user response:

You use Dictionary<TKey,TValue> when you need to store values with some unique keys associated to them, and accessing them by that key is convenient for you.

I don't know why you use dictionary here. Your user name must not be unique I think. So if user name is not unique then how can u store all user in a dictionary. I think you should use list instead of Dictionary.

Dictionary<string, Dictionary<string, int>> users = new Dictionary<string, Dictionary<string, int>>()
            {
                { "A", new Dictionary<string, int>(){
                        {"sub1", 10},
                        {"sub2", 20},
                        {"sub3", 30}
                    }
                },
                 { "B", new Dictionary<string, int>(){
                        {"sub1", 10},
                        {"sub2", 40},
                        {"sub3", 30}
                    } 
                }
            };


            var result = users.OrderBy(x => x.Key).ToDictionary(m => m.Key, m => m.Value.Sum(k => k.Value));

Dictionary is pretty fast, well optimized and offer the performance you need in most cases. But in most of the cases it doesn't really matter, the performance of a chained list of key-value pairs would have also been enough.

  • Related