2013-10-10 2 views
4

Используя text/template, мне нужно выяснить, имеет ли какой-либо объект в массиве определенное значение свойства.Проверьте, существует ли значение в вложенном массиве с пакетом шаблонов

Скажем, у меня есть список людей (JSON):

[ 
    {"name": "ANisus", "sex":"M"}, 
    {"name": "Sofia", "sex":"F"}, 
    {"name": "Anna", "sex":"F"} 
] 

Используя шаблон, я хочу, чтобы этот вывод:

Females: 
Sofia 
Anna 

Но заголовок, Females:, должен только показать в случае, если на самом деле есть любое лицо с sex, установленное на F. Как я могу выполнить это в системе шаблонов? Моя первая попытка была с помощью переменного:

{{$hasFemale := 0}} 
{{range .}}{{if eq .sex "F"}}{{$hasFemale := 1}}{{end}}{{end}} 
{{if $hasFemale}}Female:{{end}} 

я не получил эту работу, потому что $ hasFemale в пределах диапазона в другой области, а не такие же, как один инициированы с 0. Я могу» t, похоже, найдет способ изменить переменную после ее запуска.

«Работа» Пример: http://play.golang.org/p/T-Ekx7n9YQ

И я не могу переместить эту логику к приложению; это должно быть сделано в шаблоне.

+1

Этот вид логики в шаблонах, вероятно, станет намного легче, когда Go 1.2 капли. (Http://golang.org/doc/go1.2#text_template). Может быть, попробуй чаевые? Я думаю, что у него уже есть операторы сравнения шаблонов, которые прекрасно работают, но не уверены. – Intermernet

+0

О, это может быть способ. Но моя компания (у меня есть мой босс, чтобы принять меня с помощью Go: D), возможно, возникли проблемы со мной, используя подсказку. Я также добавил рабочий пример к вопросу о том, с кем люди будут играть. – ANisus

+1

Go 1.2 должен быть выпущен в декабре, поэтому теперь стоит начать экспериментировать с ним, так что к тому моменту, когда он будет выпущен как стабильная версия, вы уже воспользуетесь новыми функциями. Блокировка функций была в сентябре, поэтому теперь это должен быть довольно стабильный API. – Intermernet

ответ

4

Я решил бы это иначе. Обычно вы не хотите, чтобы состояние было в шаблонах, они должны быть простыми.

Как вы только хотите знать, есть ли в вашем наборе данные женщины, определите метод HasFemales и позвоните ему из шаблона. Вы не обязательно должны определения структуры, вы можете использовать пользовательский тип и определение, как это (your modified example on play):

type People []interface{} 

func (p People) HasFemale() bool { 
    for _, v := range p { 
     if m, ok := v.(map[string]interface{}); !ok { 
      return false 
     } else if _, ok := m["sex"]; ok && m["sex"] == "F" { 
      return true 
     } 
    } 
    return false 
} 

Ваш шаблон будет выглядеть следующим образом:

{{if .HasFemale}}Female: 
    {{range .}}{{if eq .sex "F"}}{{.name}}{{end}}{{end}} 
{{end}} 

Это , конечно, не как тип безопасный как структура, а не так хорошо, как структура, поэтому я рекомендую с использованием функции отражения encoding/json для сопоставления значений структуре и определения метода. Это также дает возможность кэшировать результат .HasFemale внутренне, поэтому вам не нужно каждый раз перебирать итерацию.

Update относительно вашего комментария:

У меня есть приложение Go, которая принимает два аргумента: 1) файл шаблона и 2) файл в формате JSON. Он выполняет шаблон с данными и выводит файл. Затем выходной файл передается в wkhtmltopdf для генерации pdf. Каждая пара шаблонов/данных имеет произвольные структуры данных вне моего контроля, поэтому приложение Go должно быть общим

В этом случае сделайте HasFemale общий. Это похоже на то, что вы делали в своем вопросе, но имеет смысл абстрагировать вложенность диапазона, позволяя вам сохранять результат в переменной и иметь состояние во всем шаблоне.Пример:

type Data []interface{} 

func (p Data) HasField(name string, value interface{}) bool { 
    for _, v := range p { 
     if m, ok := v.(map[string]interface{}); !ok { 
      return false 
     } else if _, ok := m[name]; ok && reflect.DeepEqual(m[name], value) { 
      return true 
     } 
    } 
    return false 
} 

Пример использования:

{{$hasFemale := .HasField "sex" "F"}} 
{{if $hasFemale}}Female: 
    {{range .}}{{if eq .sex "F"}}{{.name}}{{end}}{{end}} 
{{end}}` 
+0

Мне нравится идея, и я буду использовать, если бы мог. Однако мои входящие данные поступают из json-файла с произвольной структурой, поэтому приложение Go может, в моем случае, не быть жестко привязанным к конкретным структурам данных. Следующая пара шаблонов/данных может содержать списки продуктов разных типов, а не людей. – ANisus

+0

Я обновил свой ответ. – nemo

+0

Да! Теперь ты задумался. Хотя я не могу использовать тип данных из-за сложности структуры, я могу создать шаблонную функцию с тем же шаблоном '{{if hasField. "sex" "F"}} '. Благодаря! – ANisus

Смежные вопросы