Search code examples
c#algorithmsearcha-star

Getting the lowest value of a List<Struct.int>


I've got a struct which contains a few int and bool members, and I'm looking to obtain the lowest value from the list (actually making an A* Search based Path Finder).

Basically, my object looks like this:

    public struct Tile
    {
        public int id;
        public int x;
        public int y;
        public int cost;
        public bool walkable;
        public int distanceLeft;
        public int parentid;
    }

And I want to get the item with the lowest distanceLeft. The list is declared like so:

        List<Structs.Tile> openList = new List<Structs.Tile>();

And values are assigned in this manner:

        while (pathFound == null)
        {
            foreach (Structs.Tile tile in map)
            {
                foreach (Structs.Tile tile1 in getSurroundingTiles(Current))
                {
                    if (tile1.x == tile.x && tile1.y == tile.y)
                    {
                        Structs.Tile curTile = tile1;
                        curTile.parentid = Current.id;
                        curTile.distanceLeft = (Math.Abs(tile.x - goalx) + Math.Abs(tile.y - goaly));
                        if (curTile.distanceLeft == 0)
                        {
                            pathFound = true;
                        }
                        openList.Add(curTile);
                    }
                }
            }
            foreach (Structs.Tile tile in openList)
            {

            }
        }

If I had to guess I'd say this is either very difficult or far more complex than I'm making it sound, or incredibly easy and I'm just confused.

I did think about scrolling through the list and comparing each item to its lower counterpart, but that seems unreasonable considering the age we're in, it just seems there would be a simpler way. I don't care for the order of the list, as I am assigning each item an index from which I can call it.

Thanks in advance!


Solution

  • There is not one LINQ extension method that returns the object with a minimum value, but you can write one yourself. The following class does what you want on any non-empty enumerable:

    public static class MyExtensions
    {
        public static TSource MinOf<TSource>(
            this IEnumerable<TSource> source,
            Func<TSource, int> selector)
        {
            // Get the enumerator.
            var enumerator = source.GetEnumerator();
            if (!enumerator.MoveNext())
                throw new InvalidOperationException("The source sequence is empty.");
    
            // Take the first value as a minimum.
            int minimum = selector(enumerator.Current);
            TSource current = enumerator.Current;
    
            // Go through all other values...
            while (enumerator.MoveNext())
            {
                int value = selector(enumerator.Current);
                if (value < minimum)
                {
                    // A new minimum was found. Store it.
                    minimum = value;
                    current = enumerator.Current;
                }
            }
    
            // Return the minimum value.
            return current;
        }
    }
    

    Put it in a file in your project and call it like this:

    openList.MinOf(tile => tile.distanceLeft);
    

    This is more efficient than ordering the entire sequence (using OrderBy) and then taking the first value (using First).