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の2番目の引数は、Tからプロパティを抽出する手段であり、比較に関連しています。匿名クラスを使用してまったく同じ抽象化を簡単に実装できますが、それほど簡潔ではありません。

  3. 最初の引数の前にある奇妙なthis修飾子は、これが拡張メソッドであると言っています。これは、糖衣構文の目的にのみ役立ちます。メソッドがこのように定義されている場合、それは最初の引数のインスタンスで呼び出すことができることを意味します(その前にthis修飾子があります)。これにより、次のようなコードを記述できます。

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

Utilityクラスを明示的に指定する代わりに、静的メソッドは次のように定義されます。

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

おそらくこの高レベルの抽象化は必要ないでしょう(そしてそれに直面すると、Javaは今日それのために構築されていません)ので、あなたがしたいのは、反復可能なleftStopsと別のStopcurrentStopを入力して見つけるMinByの代わりにメソッドを定義することですleftStopsからcurrentStopに最も近いストップ。

何かのようなもの:

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

それが終わったら、NearestNeighbors自体に目を向けましょう。それは何yield returnですか?これは、.Netでイテレータを実装するための非常に強力な方法です。その動作についての完全な説明は私たちの議論の範囲を超えていると思うので、その機能を維持する方法でこの機能を使用しないようにメソッドを書き直しました(そして最初の引数のこの修飾子を削除しました):

 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. next-stop =first-stop
  3. ストップリストから次のストップを削除する
  4. 次の停車地に最も近い停車地を見つけて、next-stop=closestを設定します
  5. さらに停車地がある場合は、3に進みます
  6. 訪問した順に停車地を返します。

うまくいけば、それは今より明確になっています。

于 2012-09-06T05:56:58.473 に答える