❔ Using Linq to Add or Update Score in Highscore List Object
Hi,
I created a Highscore object, which consists of an IntValue and StringValue objects. I am trying to use Linq to add or update a highscore to the list. The list contains a name and the corresponding score. I want to be able to project a name and if the name exists, select it's IntValue and add to it the score, otherwise, if the projected name does not exist within the object, I want to add it. I was thinking of something like highscores.Where(x => x.StringValue.Equals("Player).AddOrUpdate(y=>y.IntValue+=thisScore));
I thought maybe I would need to create my own IEnumberable AddOrUpdate, and I tried to make something, but then I got really stuck. At this point I really don't know what I am doing, but I really want to understand and know how to do this. I would very much prefer not to use Fors and ForEachs within this code, because I have multiple if statements in a block that are running inside a for loop, and they are one lines. If I have to do long hand code, I'm going to have to copy and paste that 8 times and make it really messy and complicated. Thank you in advance for the help!
4 Replies
What's your current code for that
.AddOrUpdate()
method?This is what I have
public class Highscore
{
public string StringValue { get; set; }
public int IntValue { get; set; }
public Highscore(string stringValue, int intValue)
{
StringValue = stringValue;
IntValue = intValue;
}
}
public static class HighscoreExentions
{
public static IEnumerable<Highscore> AddOrUpdate(
this IEnumerable<Highscore> highscores, string name, int value=0)
{
if (highscores.Any(x => x.StringValue == name))
{ highscores.Where(x => x.StringValue == name).Select(y => y.IntValue += value); }
else { highscores.ToList().Add(new Highscore(name, value)); }
return highscores;
}
}
Before I wrote this post, I didn't even have that, because I was trying to do it without an extension method, or as minimally as possible. I thought I could cast or project a propsed value and use something like DefaultIfEmpty or Where to add or update. This looks like it loops through the list several times, and in that several more times. I want to be as efficient as possible, as the highscore list could end up be hundreds, of entries long.
I had an issue in another part of the project, where I was looping through a list inside another loop, both lists were several hundred entries long, and I was originally doing that to select items that matched each other, and then do something with that. That loop inside a loop then perform, I found was taking 40 seconds, and I have a Ryzen 7 3700 8 Core CPU.
LINQ is for queries, and not really meant for doing updates/mutations. the issue you are running into here is because of that
LINQ uses deferred execution. when you do
highscores.Where(x => x.StringValue == name).Select(y => y.IntValue += value);
, it returns an IEnumerable<int>
object that represents the query, but it does not actually do the query until you start enumerating elements from that object
in other words, the code you have in the if
block does exactly nothing
the code you have in your else
also does nothing, but for a different reason. when you call highscores.ToList()
, it copies all of the elements enumerated from highscores
into a new list. you do not save that list anywhere, so all that work is thrown away
it is pretty easy to create a functional alternative to AddOrUpdate
, which might look something like: this is as efficient as an operation like this can be
since you mentioned you were running into problems, though, the best solution may be an entirely different approachWas this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.