map - goでのマップの型変換

map type-conversion go

typedefが指定された場合: "type ID int"

map [ID] intをmap [int] intに変換することは可能ですか?

私はもう試した:

map[int]int(m)


と同様

m.(map[int]int)


どちらもうまくいかないようです:
http://play.golang.org/p/oPzkUcgyaR

何かアドバイス?



いくつかの人が尋ねたので、詳細を編集します。

私がやろうとしているのは、リーグを獲得することです。

「チーム」はたくさんあり、それぞれにいくつかの統計があります。統計ごとに、最高得点の場合は10ポイント、2番目の場合は9ポイントを獲得します。

私はこれを次のようにモデル化しました:

// Each team's statistics:
type StatLine map[StatID]float64

// The whole league:
map[TeamID]StatLine

// And I want to score that whole league with:
func score(s map[TeamID]StatLine) map[TeamID]int

// Only, is't also handy to score individual players:
func score(s map[PlayerID]StatLine) map[PlayerID]int


そして、score()を2回(同じロジックであるため)書いたり、マップ全体をコピーしたりしないのは素晴らしいことです。

PlayerIDとTeamIDがintである場合があります。そのため、スコア(s map [int] int)を記述して型変換を実行できるかどうか知りたいと思いました。ただし、SteveMcQwarkは、これがなぜ悪い考えであるのかを明らかにしています。

ジェネリック医薬品でこれを解決できると思いますが、すぐには出てこないでしょう。他のアイデアはありますか?

ありがとう!
答え
Goでジェネリックスを本当に実行したい場合は、インターフェースが必要です。このインターフェースは、チーム用とプレーヤー用の2つのタイプで実装されます。スコア関数は、このインターフェイスタイプのオブジェクトを引数として取り、チームまたはプレーヤーのどちらで動作しているかを認識せずに、共通のスコアリングロジックを実装します。以上が概要です。詳細は次のとおりです。

インターフェイスのメソッドセットは、スコア関数が必要とする関数とまったく同じです。必要と思われる2つの方法から始めましょう。

type scoreable interface {
    stats(scID) StatLine  // get statLine for ID
    score(scID, int)      // set score for ID
}


汎用のスコアリング可能なIDタイプ

type scID int


このインターフェイスを実装できるタイプは、TeamIDやPlayerIDではなく、それらのマップを保持するタイプです。さらに、これらの各タイプには、StatLineマップとスコアマップの両方のマップが必要です。構造体はこのために機能します:

type teamScores struct {
    stats map[TeamID]StatLine
    scores map[TeamID]int
}


スコアリングを実装すると、

func (s *teamScores) stats(id scID) StatLine {
    return s.stats[TeamID(id)]
}

func (s *teamScores) score(id scID, sc int) {
    s.scores[TeamID(id)] = sc
}


ちょっと待ってください。 scIDからTeamIDへのその型変換。安全ですか? TeamIDを持たないという低エンジニアリングのアプローチを採用したほうがいいのではないでしょうか。まあ、これらの方法が賢明に使用されている限り、それは安全です。 struct teamScoresは、TeamIDのマップをTeamIDの別のマップに関連付けます。間もなく作成される汎用関数スコアは、この構造体を引数として取り、正しい関連付けが与えられます。 TeamIDとPlayerIDを混在させることはできません。それは価値があり、十分に大きなプログラムではこの手法を正当化できます。

PlayerIDにも同じことを行い、同様の構造体を定義して、2つのメソッドを追加します。

スコア関数を1回記述します。このように始めます:

func score(s scoreable) {
    for


エラーが発生しました。繰り返し処理する方法が必要です。 IDのリストを取得するのが適切な解決策です。そのメソッドを追加しましょう:

type scoreable interface {
    ids() []scID          // get list of all IDs
    stats(scID) StatLine  // get statLine for ID
    score(scID, int)      // set score for ID
}


そしてteamScoresの実装:

func (s *teamScores) ids() (a []scID) {
    for tid := range s.stats {
        a = append(a, scID(tid))
    }
    return
}


今どこにいたの?

func score(s scoreable) {
    // lets say we need some intermediate value
    sum := make(map[scID]float64)
    // for each id for which we have a statLine,
    for _, id := range s.ids() { // note method call
        // get the statLine
        stats := s.stats() // method call
        // compute intermediate value
        sum[id] = 0.
        for _, statValue := range stats {
            sum[id] += statValue
        }
    }
    // now compute the final scores
    for id, s := range sum {
        score := int(s) // stub computation
        s.score(id, score) // method call
    }
}


この関数は、* scoreableのようなインターフェイスへのポインターではなく、スコアリング可能なインターフェイスタイプをとります。インターフェイスは、ポインタタイプ* teamScoresを保持できます。インターフェイスへの追加のポインタは適切ではありません。

最後に、ジェネリック関数を呼び出すには、teamScoresタイプのオブジェクトが必要です。おそらくすでにリーグの統計情報を持っていますが、まだスコアマップを作成していない可能性があります。あなたはこのように一度にこれをすべて行うことができます:

ts := &teamScores{
    stats:  ...your existing map[TeamID]Statline,
    scores: make(map[TeamID]int),
}


コール:

score(ts)


そして、チームのスコアはts.scoresになります。
関連記事

c++ - C++ std::mapキーソート比較関数?

postgresql - 自サーバーでのNominatim APIインストールエラー

memory - Go:マップキーを再利用する場合のメモリ使用量の増加

java - JTextField要素がすでにマップに割り当てられているマップを使用してsetTextメソッドを適用する方法

c++ - ブーストaccumulator_setをSTLマップに格納

types - 地図とavroのレコードの違いは何ですか?

java - 同じオブジェクト上の複数のデータ構造

jquery - Jquery maphilightプラグインを使用してクリック時の領域のfillColorを変更する

c++ - 構造体をキーとするマップを削除するとセグメンテーション違反

c++ - boost::bindを使用してstd::mapを反復処理する