Get elements from a list based on enum

I have an enum indicating the eligibility of a spawn.

protected enum SpawnEligibility
{
    Worst,
    Ok,
    Optimal
}

Then, I have a function to return the eligibility.

protected virtual SpawnEligibility GetEligibility(Vector3 spawn)
{
    var players = _instance.FindPlayersInRadius(spawn, 10).ToList();
    if (!players.Any())
        return SpawnEligibility.Optimal;

    return players.Any(x => _instance.CanSeeLocation(x, spawn))
        ? SpawnEligibility.Worst
        : SpawnEligibility.Ok;
}

When selecting a spawn I'd like to pick a random spawn from those that have the highest level of eligibility, though they may all be Worst, Ok, Optimal, or a mix. This is my code which I was using to select a spawn.

public virtual Vector3 FindSpawn(BasePlayer player) => 
    _spawns.OrderByDescending(GetEligibility).First();

How can I either make a dictionary with a Spawn key and SpawnEligibility value OR return a random element from my list without calling the GetEligibility function again?

Jon Skeet
people
quotationmark

It sounds to me like you want to group by eligibility, then order those groups by their key (descending), then take the first group:

var bestSpawnGroup = _spawns
    .GroupBy(GetEligibility)
    .OrderByDescending(g => g.Key)
    .First();

If the method group conversion for GetEligibility causes problems (I can never remember the circumstances under which it does) you can just call it from a lambda expression:

var bestSpawnGroup = _spawns
    .GroupBy(s => GetEligibility(s))
    .OrderByDescending(g => g.Key)
    .First();

You can then tell the eligibility of that group (its Key) and find a random element in the group. (You could either convert the group to a list/array or use code like this to pick a random element from the group without materializing it.)

people

See more on this question at Stackoverflow