5

ポイント型の多次元ポイントのリストがあります。

sort.Sortインターフェイスを実装し、で並べ替えることができるようになりましたy value

例えば

type Points []*Point

func (points Points) Len() int {
    return len(points)
}
func (points Points) Less(i, j int) bool {
    return points[i].y < points[j].y
}
func (points Points) Swap(i, j int) {
    points[i], points[j] = points[j], points[i]
}

type Point struct {
    x int
    y int
    country_id int
}

x valueここで、ポイントをではなく で並べ替えたいと思いますy value

私のアイデアは、グローバル フラグ (並べ替えの前にオンまたはオフに切り替えることができる) を持つ if ステートメントを使用することです。

func (points Points) Less(i, j int) bool {
    if SORT_BY_X {
        return points[i].x < points[j].x
    }
    return points[i].y < points[j].y
}

これを行うより良い方法はありますか?Less を複数回実装する必要がありますか? たとえば、データのテーブルを列ごとに並べ替えるとどうなりますか?

4

2 に答える 2

7

ああ、これは興味深いですsort.Sort()。型が順序付けといくつかの配列操作を定義することを期待しています。「X ソート可能なポイント リスト」と「Y ソート可能なポイント リスト」タイプを使用できますが、配列 ops を共有すると、Go は継承を使用しないため、他の言語とは動作が異なります。

私が考えた最初の方法は、それぞれが独立して を実装する と の型XSortablePointsを作成し、その時点で必要なインスタンスにインスタンスを変換することですYSortablePointssort.InterfacePoints

次に、nemo にはより良い方法がありました。型の埋め込みによりXSortablePointsYSortablePoints配列操作の関数を共有することができます。また、nemo はソート可能な型を変数に保存しません。これは、この 1 つのソート呼び出しに対してのみ存在するため意味があります。調整されたサンプル コードは次のとおりです: http://play.golang.org/p/wNm-ilM18n

これらのアプローチはいずれも、キャスト時にポイント データを実際にコピーするものではなく、スライス ヘッダーのみをコピーすることに注意してください。これは、最初の例で出力されたポインター アドレスを見ればわかります。

あなたはより洗練されたものになることができます: http://play.golang.org/p/4PmJVi2_7Dで任意の比較関数を取る Points.Sort があります。より多くの型を定義するという強引なアプローチは、順序付けが 2 つまたは 3 つしかない限り問題ないと思いますが、状況はさまざまです。ここでのポイントよりもはるかに大きな型の場合、コピーを避けるために、値ではなくポインターを取るように比較子を定義することをお勧めします。

re: SORT_BY_X: 私は通常、プログラムの実行時に更新するグローバル モード設定変数を避けます。たとえば、いつか 2 つの並列ゴルーチンがあり、両方が同時にグローバルにアクセスすると問題が発生する可能性があります。または、SORT_BY_X の初期値が の場合に一部のコードが機能し、別のタスクが実行された後falseに残されたため、いつか失敗する可能性があります。trueモード変数が必要であることに気付いた場合は、それをグローバルにする代わりに、関数パラメーターにするか、オブジェクトにアタッチすることができるかどうかを判断してください。

最後に、必要な高レベルの機能の一部を既に提供しているパッケージがあるかもしれません。たとえば、ここにリストされている地理データに関連するパッケージがいくつかあります: https://code.google.com/p/go-wiki/wiki/Projects#GIS

于 2013-11-03T23:32:41.303 に答える