Как фильтровать информацию из списков

Вывод информации по отдельным категориям

Допустим, мы получили от сервера массив с данными. Наша задача — вывести по отдельности информацию по определенным категориям.

В переменных пользователя наш массив выглядит так:

{
  "name": "Катя",
  "names": [
    "Василиса",
    "Вася",
    "Катя",
    "Ярик",
    "Джек",
    "Джейк",
    "Гиви",
    "Максим",
    "Ярослава",
    "Катя",
    "Владимир",
    "Финн",
    "Вилли",
    "Катя",
    "Казимир",
    "Ибрагим"
  ],
  "orders": [
    {
      "id": 1,
      "status": "success",
      "title": "Холодильник",
      "price": "54 000 ₽"
    },
    {
      "id": 2,
      "status": "fail",
      "title": "Микроволновка",
      "price": "5 000 ₽"
    },
    {
      "id": 3,
      "status": "delivering",
      "title": "Люля-Кебаб",
      "price": "540 ₽"
    },
    {
      "id": 4,
      "status": "delivering",
      "title": "Пицца",
      "price": "655 ₽"
    },
    {
      "id": 5,
      "status": "success",
      "title": "Playstation 5",
      "price": "154 000 ₽"
    },
    {
      "id": 6,
      "status": "success",
      "title": "Кулебяка с рыбой",
      "price": "540 000 ₽"
    }
  ]
}

Итак, нам нужно, чтобы в бот выводилась отфильтрованная разными способами информация.

Для начала будем выводить имена. Используем компонент Сообщение:

1. Выведем из массива всех Кать, скопировав в Сообщение хелпер:

{{filter names name}}

Протестируйте хелпер в песочнице →

2. Теперь выведем всех Кать нумерованным списком, скопировав в Сообщение такую конструкцию:

{{#filter names name}}
{{add @index 1}}. {{this}}
{{else}}
Не найдено такого имени
{{/filter}}

В этом случае, в бот придет нумерованный список всех Кать:

Протестируйте хелпер в песочнице →

3. Таким хелпером мы найдем в списке и выведем в бот всех Василис, в данном случае, она у нас одна:

{{filter names "Василиса"}}

Протестируйте этот хелпер в песочнице →

4. Так получаем все имена длинной 4 символа:

{{filter names 4 prop="length"}}

Бот прислал по порядку все имена из четырех букв, которые есть в нашем массиве:

Протестируйте этот хелпер в песочнице →

5. Выведем нумерованным списком все имена, имеющие четыре буквы.

Для этого добавим в Сообщение хелпер:

{{#filter names 4 prop="length"}}
{{add @index 1}}. {{this}}
{{else}}
Не нашлось таких имен
{{/filter}}

Получим в боте тех же персон, что и в прошлом примере, но пронумерованных:

Протестируйте этот хелпер в песочнице →

6. Получим первые два имени длинной 4 символа и выведем их списком:

{{#filter names 4 prop="length" limit=2}}
{{add @index 1}}. {{this}}
{{else}}
Не нашлось таких имен
{{/filter}}

Результат:

Протестируйте этот хелпер в песочнице →

7. Переименовываем this и @index (вместо index — id, вместо this — имя).

Копируем данную конструкцию в Сообщение:

{{#filter names name as |name id|}}
ID: {{id}}; Имя: {{name}}
{{else}}
Не найдено такого имени
{{/filter}}

В результате @index превратился в ID и все {{name}} вывелось таким списком:

Протестируйте этот хелпер в песочнице →

Кроме имен, в массиве есть информация о заказах, которую тоже можно вывести:

1. Выводим массивом, для записи в переменную все успешные заказы из переменных:

"orders": [
    {
      "id": 1,
      "status": "success",
      "title": "Холодильник",
      "price": "54 000 ₽"
    },
    {
      "id": 2,
      "status": "fail",
      "title": "Микроволновка",
      "price": "5 000 ₽"
    },
    {
      "id": 3,
      "status": "delivering",
      "title": "Люля-Кебаб",
      "price": "540 ₽"
    },
    {
      "id": 4,
      "status": "delivering",
      "title": "Пицца",
      "price": "655 ₽"
    },
    {
      "id": 5,
      "status": "success",
      "title": "Playstation 5",
      "price": "154 000 ₽"
    },
    {
      "id": 6,
      "status": "success",
      "title": "Кулебяка с рыбой",
      "price": "540 000 ₽"
    }
  ]

Используем для этого хелпер JSONstringify

{{JSONstringify (filter orders "success" prop="status")}}

Вот что придет в бот:

Протестируйте этот хелпер в песочнице →

2. Выведем списком заказы, которые доставляются:

{{#filter orders "delivering" prop="status"}}
{{add @index 1}}. {{title}}
{{/filter}}

Бот прислал все заказы со статусом "доставляется".

Протестируйте этот хелперр в песочнице →

3. Используя limit="1", найдем первый попавшийся Playstation 5, определим номер заказа и выведем цену:

{{#filter orders "Playstation 5" prop="title" limit="1"}}
Номер заказа: {{id}}
Позиция: {{title}}
Цена: {{price}}
{{else}}
Вы еще не купили Playstation 5
{{/filter}}

Данные будут выводиться из этих переменных пользователя:

"id": 5,
      "status": "success",
      "title": "Playstation 5",
      "price": "154 000 ₽"

Протестируйте этот хелпер в песочнице →

Поиск переменной в многоуровневом списке

Например, из внешнего источника в бот пришел список с данными. В нём нужно найти информацию о том, подписан ли пользователь на рассылку Email.

Переменная Email находится в contactMethod, подписан пользователь или нет, можно увидеть в isUserSubscribed.

{
  "last_request": {
    "responseStatus": "Success",
    "clientData": {
      "userSubscriptions": [
        {
          "isUserSubscribed": true
        },
        {
          "contactMethod": "Sms",
          "isUserSubscribed": true
        },
        {
          "contactMethod": "Email",
          "isUserSubscribed": false
        },
        {
          "contactMethod": "Mail",
          "isUserSubscribed": true
        },
        {
          "contactMethod": "WA",
          "isUserSubscribed": true
        },
        {
          "contactMethod": "VK",
          "isUserSubscribed": true
        }
      ]
    }
  }
}

Проделаем следующие шаги для поиска статуса Email рассылки пользователя:

1. Создаем локальную переменную с именем filtered и помещаем туда результат хелпера filter.

2. Хелпером filter отбираем только те элементы массива, в которых contactMethod — это строка "Email"

Свойство prop — это чтобы указать свойство внутри объекта внутри массива.

Свойство limit — чтобы не перебирать массив дальше, после того, как найдено первое совпадение.

3. В локальной переменной @vars.filtered теперь отфильтрованный список. Там или пусто, если нет contactMethod = "Email", или там будет единственный элемент, где можно получить доступ к второй переменной объекта isUserSubscribed.

Подробнее про хелпер {{#vars}} можно узнать тут.

4. Наличие переменной isUserSubscribed и её значение проверяем хелпером #if. Если массив не пустой, значит там объект в нулевом элементе, и если он true, то выполнится основной блок, до {{else}}. Если массив пуст (Email не найден), или в isUserSubscribed находится false, то выполнится та часть, что после {{else}}.

{{#filter
    last_request.clientData.userSubscriptions
    "Email"
    prop="contactMethod"
    limit=1
}}
  {{~#if isUserSubscribed~}}
  Пользователь подписан на рассылку в Email
  {{~else~}}
  Пользователь не подписан на рассылку в Email
  {{~/if~}}
{{else}}
Записи о рассылке Email вообще не найдено
{{/filter}}

Протестируйте этот кейс в песочнице →

Вывод информации от меньшего значения к большему

Хелпер sortBy поможет сделать сортировку от меньшего значения к большему.

Например, с помощью такого шаблона можно вывести возраст из переменной age от младшего к старшему:

{{stringify (sortBy array "age")}}

В этом шаблоне array — это массив объектов, в котором проводим сортировку, age — это переменная, по которой будет выполняться сортировка.

Протестируйте этот кейс в песочнице →

Вывод информации от большего значения к меньшему

Хелпер reverse поможет сделать сортировку от большего значения к меньшему.

Используем список из примера выше. Выведем с помощью шаблона возраст из переменной age от старшего к младшему:

{{stringify (reverse (sortBy array "age"))}}

В этом шаблоне array — это массив объектов, в котором проводим сортировку, age — это переменная, по которой будет выполняться сортировка.

Протестируйте этот кейс в песочнице →

Прибавление определенного числа ко всем значениям переменной

Если нужно прибавить, например, число 500 всем значениям в переменной price, которые есть в списке, то подойдет такой шаблон:

{{#vars}}
   {{var "listLocalCopy" list ~}}
  {{#each @vars.listLocalCopy}}
    {{#var "changeKey" ~}}
      listLocalCopy.{{@index}}.price
    {{~/var}}
    {{var @vars.changeKey (add this.price 500) ~}}
  {{/each}}
  {{stringify @vars.listLocalCopy}}
{{/vars}}

В песочнице можно протестировать этот пример или поменять список на свой. Кейс в песочнице дополнен комменратиями от разработчиков.

Исключение пустых строк из списка

В некоторых случаях в бот может прийти список с пустыми строками. Чтобы в сообщении вывелись только заполненные пункты, можно использовать такой шаблон:

{{#each list}}
{{#if this}}
{{this}}
{{/if}}
{{/each}}

Протестируйте этот кейс в песочнице →

Как вывести несколько значений из строки

Этот кейс будет полезен в случае, если нужно вывести первые несколько значений, которые идут с начала строки со словами разделенными пробелами. В нашем примере строка с именами. Из неё мы выведем первые 5 имен.

Число выводимых слов всегда должно быть меньше числа слов в тексте, иначе шаблон не сработает.

Вывод нужного количества позиций списка происходит так:

1. Разрезаем строку на слова по пробелу и записываем полученный список в локальную переменную @vars.list

2. Берем все элементы списка с начала до 5, сообщаем хелеперу before, сколько отступить от конца. Это число получаем, вычитая из длины списка количество элементов списка, которые нам нужны.

Эти элементы записываем в локальную переменную sliced.

3. После этого выводим через join. Этот хелпер объединяет массив через определенную строку, в нашем случае пустую строку.

В итоге получаем такой шаблон:

{{#vars}}
{{var "list" (split name " ") ~}}
{{var "sliced" (before @vars.list (subtract @vars.list.length 5)) ~}}
{{join @vars.sliced " "}}
{{/vars}}

В песочнице вы можете протестировать этот кейс, используя свои значения.

В начало ↑