简体   繁体   中英

C# Linq add element to list of object where condition is met

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);
    }

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);
}

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));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM