Jacob Stein
Jacob Stein

Reputation: 322

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?

Upvotes: 2

Views: 136

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500275

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

Upvotes: 5

Related Questions