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