0

我正在尝试实现这一点,但我找不到一篇好的论文或描述如何做到这一点,你们能指出我正确的方向吗?我确实在 C# 中有一个实现,但我不知道将代码转换为 Java。

根据评论,我添加了一些我无法转换为 Java 的 C# 代码:

//T with the smallest func(t)
      static T MinBy<T, TComparable>(this IEnumerable<T> xs, Func<T, TComparable> func) where TComparable : IComparable<TComparable>{
        return xs.DefaultIfEmpty().Aggregate((maxSoFar, elem) => func(elem).CompareTo(func(maxSoFar)) > 0 ? maxSoFar : elem);
      }

      //returns an ordered set of nearest neighbors
      static IEnumerable<Stop> NearestNeighbors(this IEnumerable<Stop> stops){
        var stopsLeft = stops.ToList();
        for (var stop = stopsLeft.First(); stop != null; stop = stopsLeft.MinBy(s => Stop.Distance(stop, s))){
            stopsLeft.Remove(stop);
            yield return stop;
        }
      }
4

1 回答 1

0

我假设你不熟悉 C#。因此,我将尝试简短地解释一些事情。

  1. IEnumerable<T>是 C# 等价于 java 的Iterable<T>

  2. Func<T, V>是一个方法的抽象,输入是 T,返回值是 V。C# 与 Java 不同,支持闭包,但它们实际上就像 java 匿名类,没有所有的语法大惊小怪。所以基本上, MinBy 的第二个参数是一种从 T 中提取属性的方法,与比较相关。您可以使用匿名类轻松实现相同的抽象,但它不会那么简洁。

  3. 第一个参数之前的奇怪this修饰符是说这是一个扩展方法。它仅用于语法糖目的。当一个方法像这样定义时,这意味着它可以在第一个参数的实例上调用(它前面有 this 修饰符)。这使您可以编写如下代码:

    IEnumerable<String> seq = getS();
    seq.MinBy(/*bla*/);

而不是显式指定 Utility 类,而是在以下位置定义静态方法:

   MyUtility.MinBy(s, /*bla*/);

您可能不需要这种高级别的抽象(让我们面对现实,Java 根本不是为它构建的)所以您想要做的是定义一个方法而不是 MinBy 输入一个 Iterable leftStops 和另一个 Stop currentStop 并找到从 leftStops 到 currentStop 的最近站点。

就像是:

Stop findClosest(Stop currentStop, Iterable<Stop> left stops) {/*implement me*/}

完成后,让我们转向 NearestNeighbors 本身。那是什么yield return?这是在 .Net 中实现迭代器的一种非常强大的方法。我觉得对其工作原理的完整解释超出了我们讨论的范围,因此我重写了不使用此功能的方法,以保留其功能(并删除了第一个参数的 this 限定符):

 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;
      }

所以我们剩下以下算法:

  1. 输入停靠点列表
  2. 下一站 = 第一站
  3. 从停止列表中删除下一站
  4. 找到离下一站最近的站点并设置 next-stop=closest
  5. 如果有更多站点,请转到 3
  6. 按访问顺序返回站点。

希望现在更清楚了。

于 2012-09-06T05:56:58.473 回答