2

I have a player class

public class Player : Person
{
    public List<int> SetPoints;
}

And a game class

private List<Player> Players;

public Game(List<Player> players)
{
    Players = players;
}

public void Simulate()
{
    var winnerPoints = 6;
    var looserPoints = Tournament.Random.Next(0, 5);
    var winnerId = Players[Tournament.Random.Next(0, 1)].Id;

    Players.Where(p => p.Id == winnerId).Select(p => p.SetPoints).Add(winnerPoints);
}

The code demonstrates what im trying to accomplish but i cant access the SetPoints list for updating, in the selected player object. Can anyone point out what modification i need to make in order for this to work?

Thanks in advance

UPDATED

My goal was to add winnerPoints to SetPoints of one random Player object in Players, and loserPoints to the other (Players is always a list of two objects, provided by the constructor) thanks to maccettura i accomplished this by using FirstOrDefault()

    public void Simulate()
    {
        var winnerPoints = 6;
        var loserPoints = Tournament.Random.Next(0, 5);
        var winnerId = Players[Tournament.Random.Next(0, 1)].Id;

        Players.FirstOrDefault(p => p.Id == winnerId).SetPoints.Add(winnerPoints);
        Players.FirstOrDefault(p => p.Id != winnerId).SetPoints.Add(loserPoints);
    }
7
  • 1
    You likely want FirstOrDefault() instead of Where().Select(). Also, looserPoints should probably be loserPoints (its a typo) Commented May 2, 2018 at 19:11
  • The Select() will return an IEnumerable<List<int>> not a List<int>. Commented May 2, 2018 at 19:13
  • 1
    @maccettura That should be an answer IMO Commented May 2, 2018 at 19:15
  • I can't use FirstOrDefault() as i must select a random of the two Player objects in the list. I tried adding .ToList() after Select() followed by .Add(winnerPoints) but i receive an error saying i cant convert from int (winnerPoints) to List<int> - however that should be possible in theory? Commented May 2, 2018 at 19:19
  • @MikeHawkins that makes no sense. FirstOrDefault() is the same logic you have now (but working). Also, there is nothing "random" about the code you have posted. If there is some other requirement it needs to be included in the question. Please see how to add a minimal reproducible example Commented May 2, 2018 at 19:20

2 Answers 2

5

If you want a single matching Player object:

The code you are using now does not do what you think it does:

Players.Where(p => p.Id == winnerId).Select(p => p.SetPoints)

What this is doing is looking for all matches on winnerId, then selecting all of the matching lists properties. This results in an IEnumerable<List<int>>.

If you need just one Player, to do that you need to use FirstOrDefault():

var player = Players.FirstOrDefault(p => p.Id == winnerId);
//Check if player is not null, then add

This will give you a Player as the return, or the default(Player) (null) if there is no match.

Now that you have the Player object you can access the SetPoints property and Add() from there.

If you want all matching Player objects:

If you want all matching Player objects you just need to iterate over your Where() query results:

//Where() returns an IEnumerable<Player>
foreach(Player p in Players.Where(p => p.Id == winnerId))
{
    p.SetPoints.Add(winnerPoints);
}
Sign up to request clarification or add additional context in comments.

2 Comments

@MikeHawkins I was going to reply to the parent question, but I will do it here. Can you elaborate on the "random" thing you mentioned? I wanna make sure I clear that up (if its still unclear)
It's clear to me now that you have explained that FIrstOrDefault() can be used with an expression to select a Player object (in this case, by Id) and then access the list of that object. See my updated question for the logic i tried to accomplish.
1

Assuming that winnerId is unique, it would be sufficient to find a single result using FirstOrDefault:

Players.FirstOrDefault(p => p.Id == winnerId)?.SetPoints.Add(winnerPoints);

For the case (or rather, another use case) that it isn't unique, and you actually want a list of results, you could use ForEach() after a call to ToList() (or a standard foreach loop):

Players.Where(p => p.Id == winnerId).ToList().ForEach(p => p.SetPoints.Add(winnerPoints));

1 Comment

FirstOrDefault can return null, which will crash on .SetPoints. If you know you should have a matching element, use First(...), otherwise you should null check or use null propagation (?.).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.