I assume you are not familiar with C#. So I will try to explain some of the things in short.
IEnumerable<T>
is C#'s equivalent of java's Iterable<T>
Func<T, V>
is an abstraction of a method who's input is T and return value is V. C#, unlike Java, supports closures, but they are effectively like java anonymous classes, without all the syntactic fuss around. So basically, the second argument of MinBy is a means to extract the property from T is relevant for comparison. You could easily implement the very same abstraction with an anonymous class, but it will not be as concise.
The strange this
modifier that comes before the first argument is saying that this is an extension method. It solely serves a syntactic sugar purpose. When a method is define like this, it means that it can be called on the instance of the first argument (that has the this modifier before it). This allowes you to write code like:
IEnumerable<String> seq = getS();
seq.MinBy(/*bla*/);
instead of explicitly specifying the Utility class the static method is defined in:
MyUtility.MinBy(s, /*bla*/);
You probably do not need this high level of abstraction (and lets face it, java is simply not built for it today) so what you want to do is to define a method instead of MinBy that inputs an Iterable leftStops and another Stop currentStop and finds the closest stop to currentStop from leftStops.
Something like:
Stop findClosest(Stop currentStop, Iterable<Stop> left stops) {/*implement me*/}
That done, lets turn to NearestNeighbors itself. What is that yield return
? it is a very powerful way to implelent iterators in .Net. I feel that a full explanation on its workings is beyond the scope of our discussion, so I have rewritten the method not to use this feature in a way that conserves its functionality (and removed the this qualifier of its first argument):
static IEnumerable<Stop> NearestNeighbors(IEnumerable<Stop> stops){
IEnumerable<Stop> result = new List<stop>();
var stopsLeft = stops.ToList();
for (var stop = stopsLeft.First(); stop != null; stop = stopsLeft.MinBy(s => Stop.Distance(stop, s))){
stopsLeft.Remove(stop);
result.Add(stop);
}
return result;
}
So we are left with the following algorithm:
- Input a list of Stops
- next-stop = first-stop
- Remove next-stop from the Stop list
- Find the closest stop to next-stop and set next-stop=closest
- if there are more stops, go to 3
- Return the stops in the order they were visited.
Hopefully it is clearer now.