2017-09-29 9 views
0

私は次の出力に共通キーのマップと出力を比較する方法は?

コード生成、次のコードがあります。

package main 

import (
    "html/template" 
    "os" 
) 

type EntetiesClass struct { 
    Name string 
    Value int32 
} 

// In the template, we use rangeStruct to turn our struct values 
// into a slice we can iterate over 
var htmlTemplate = `{{range $index, $element := .}} 
{{range $element}}{{.Name}}={{.Value}} 
{{- end}} 
{{- end}}` 

func main() { 
    data := map[string][]EntetiesClass{ 
      "Container1": {{"Test", 15}}, 
      "Container2": {{"Test", 15}}, 
    } 

    t := template.New("t") 
    t, err := t.Parse(htmlTemplate) 
    if err != nil { 
      panic(err) 
    } 

    err = t.Execute(os.Stdout, data) 
    if err != nil { 
      panic(err) 
    } 

} 

をリンク:https://play.golang.org/p/yM9_wWmyLY
出力:

テスト= 15 テスト= 15

私がしたいですContainer1とContainer2を比較し、共通キーを持っている場合は、出力を1回だけ印刷したいだけです。

出力: テスト= 15

私はこれをどのように達成することができますか?どんな助けもありがたいですか?

+1

nit-pick:スペルは「エンティティ」で、Goにはクラスがないため、この用語を避ける必要があります。 – Peter

答えて

3

私はこれを行うには、2つの方法を考えることができます。これは、あなたが重複を排除するためにt.Executeに渡す前に、データを事前処理できることを意味しますテンプレートの実行に

を渡す前に、あなたのデータDEDUP

  1. 。これは、あなたが通常の外出を追加することができることを意味しcustom function for your template

    を追加

  2. m := map[EntitiesClass]bool{} 
    for _, ... { 
        m[ec] = true 
        // Or maybe you want to aggregate "Container 1" 
        // and "Container 2" in some way 
    } 
    

    次に、あなただけの処理されたデータを渡すことができ、テンプレート自体はほぼ変わらず

  3. :あなたはのようなものを使用してこれを行うことができますあなたが好きな数だけ EntitiesClassを受け取り、重複排除したものを返します(おそらく、オプション1の仕組みで)。あなたも何か行うことができます

    あなたの簡単な例
    {{if not customHaveSeenThisValueBefore }} 
        ... 
    {{ endif }} 
    

私はオプション1を選ぶだろうが、非常にシンプルなテンプレートを残すために最も簡単なようです。

+0

面白いことは 'map [EntitiesClass] struct {}'を使うことです。なぜなら実際に 'bool'を見る必要がないからです。空の 'struct {}'値を使用しても割り当てられないので、これは 'bool'によって使用されるメモリを節約します。 https://dave.cheney.net/2014/03/25/the-empty-struct – RayfenWindspear

+0

@RayfenWindspear地図が大きいときに使うのはいいです。しかし、boolを使用している小さなマップでは、マップ内の存在を確認する際に、より良い構文を使用します。 'm [x]' vs 'if _、ok:= m [x]; OK – cnicutar

0

これは、いくつかのフィルタリングロジックを適用します。このコードはサーバーを使用していないため、text/templateを使用しています。 html/templateと同様に動作します。構造体のスライスに追加するときは、ポインタを使用する必要があります。理由がわからない場合はhereを参照してください。 func isInSlice() boolは必要に応じて変更する必要があります。これは例として役立ちます。

package main 

import (
    "os" 
    "text/template" 
) 

type Entitie struct { 
    Results []*Data 
} 

type Data struct { 
    Name string 
    Value int32 
} 

// Change this function to mod how to filter 
func (e *Entitie) isInSlice(name string) bool { 
    for _, item := range e.Results { 
     if item.Name == name { 
      return true 
     } 
    } 
    return false 
} 

func (e *Entitie) AddData(name string, value int32) { 
    if !e.isInSlice(name) { 
     e.Results = append(e.Results, &Data{Name: name, Value: value}) 
    } 
} 

// In the template, we use rangeStruct to turn our struct values 
// into a slice we can iterate over 
var template = ` 
    {{range $i, $e := .Data.Results}} 
     {{$e.Name}} = {{$e.Value}} 
    {{end}} 
    ` 

func main() { 
    data := make(map[string]Entitie) 

    var entities Entitie 

    entities.AddData("test", 15) 
    entities.AddData("test", 15) 
    entities.AddData("test2", 15) 

    t := template.New("t") 
    t, err := t.Parse(template) 
    if err != nil { 
     panic(err) 
    } 

    data["Data"] = entities 

    err = t.Execute(os.Stdout, data) 
    if err != nil { 
     panic(err) 
    } 

} 
関連する問題