How to filter information from arrays

Display of information on individual categories

Let's say we received an array with data from the server. Our task is to display information separately by certain categories.

In Users, our array looks like this:

{
  "name": "Katya",
  "names": [
    "Vasilisa",
    "Vasya",
    "Katya",
    "Yarik",
    "Jack",
    "Jake",
    "Givi",
    "Maxim",
    "Yaroslava",
    "Katya",
    "Vladimir",
    "Finn",
    "Willie",
    "Katya",
    "Casimir",
    "Ibrahim"
  ],
  "orders": [
    {
      "id": 1,
      "status": "success",
      "title": "Refrigerator",
      "price": "$54,000"
    },
    {
      "id": 2,
      "status": "fail",
      "title": "Microwave",
      "price": "$5,000"
    },
    {
      "id": 3,
      "status": "delivering",
      "title": "Kebab",
      "price": "$540"
    },
    {
      "id": 4,
      "status": "delivering",
      "title": "Pizza",
      "price": "$655"
    },
    {
      "id": 5,
      "status": "success",
      "title": "Playstation 5",
      "price": "$154,000"
    },
    {
      "id": 6,
      "status": "success",
      "title": "Loaf with fish",
      "price": "$540,000"
    }
  ]
}

So, we need the information filtered in different ways to be output to the bot.

To begin with, we will output the names. Use Message component:

1. We will output all “Katyas” from the array by copying the helper into the Message

{{filter names name}}

There are only three Katyas in our array, so the result will be like this:

Test this helper in the sandbox

2. Now we will output all Katyas in a numbered list by copying the following construction into the Message:

{{#filter names name}}
{{add @index 1}}. {{this}}
{{else}}
No such name was found
{{/filter}}

In this case, a numbered list with all Katyas will come to the bot:

Test this helper in the sandbox

3. We will find all Vasilisas in the list with such a helper and output them to the bot, in this case, we have one Vasilisa:

{{filter names "Vasilisa"}}

Result:

Test this helper in the sandbox

4. So we get all the names with a length of 4 characters:

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

The bot sent in order all four-letter names that are in our array:

Test this helper in the sandbox

5. Output a numbered list of all four-letter names.

To do this, add a helper to the Message:
{{#filter names 4 prop="length"}}
{{add @index 1}}. {{this}}
{{else}}
There were no such names
{{/filter}}

We will get the same persons in the bot as in the previous example, but now they are numbered:

Test this helper in the sandbox

6. Get the first two names with a length of 4 characters and output them as a list:

{{#filter names 4 prop="length" limit=2}}
{{add @index 1}}. {{this}}
{{else}}
There were no such names
{{/filter}}

Result:

Test this helper in the sandbox

7. "Rename" this and @index

(instead of index - id, instead of this - name)

Copy this construction to the Message:

{{#filter names name as |name id|}}
ID: {{id}}; Name: {{name}}
{{else}}
No such name was found
{{/filter}}

As a result, @index turned into ID and everything {{name}} output as the following list:

Test this helper in the sandbox

In addition to the names, there is information about orders in the array, which can also be output:

"orders": [
    {
      "id": 1,
      "status": "success",
      "title": "Refrigerator",
      "price": "$54,000"
    },
    {
      "id": 2,
      "status": "fail",
      "title": "Microwave",
      "price": "$5,000"
    },
    {
      "id": 3,
      "status": "delivering",
      "title": "Kebab",
      "price": "$540"
    },
    {
      "id": 4,
      "status": "delivering",
      "title": "Pizza",
      "price": "$655"
    },
    {
      "id": 5,
      "status": "success",
      "title": "Playstation 5",
      "price": "$154,000"
    },
    {
      "id": 6,
      "status": "success",
      "title": "Loaf with fish",
      "price": "$540,000"
    }
  ]

1. Output all successful orders as an array to write them to the variable:

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

Here's what will come to the bot:

Test this helper in the sandbox

2. We will list the orders that are delivering:

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

The bot sent all orders with the status "delivering"

Test this helper in the sandbox

3. Let’s Find the first Playstation 5 that comes along, determine the order number and output the price:

{{#filter orders "Playstation 5" prop="title"}}
Order number: {{id}}
Item: {{title}}
Price: {{price}}
{{else}}
You haven't bought Playstation 5 yet
{{/filter}}

Result:

Test this helper in the sandbox

Variable search in a multi-level list

For example, the bot received a list with data from an external source. You need to find information in this list about a user subscription to the Email broadcast.

The Email variable is in contactMethod. You can see the user subscription validity in 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
        }
      ]
    }
  }
}

Do the following steps to find the status of the user Email broadcast:

1. Create a local variable named filtered and put the result of the filter helper there.

2. Using the filter helper, select only the array elements where contactMethod is the “Email” string.

The prop property specifies a property within the object inside the array.

The limit property allows to stop iterating through the array once the first match is found.

3. The local @vars.filtered variable has a filtered list now. It is either empty if there is no contactMethod = “Email” or there will be a single element where you can access the second variable of the isUserSubscribed object.

You can find more information about the {{#vars}} helper here →

4. The presence of the isUserSubscribed variable and its value are checked by the #if helper. If the array is not empty, there is an object in the null element, and if this object is true, the main block will be executed up to {{else}}. If the array is empty (Email was not found), or false is in isUserSubscribed, the part after {{else}} will be executed.

{{#filter
    last_request.clientData.userSubscriptions
    "Email"
    prop="contactMethod"
    limit=1
}}
  {{~#if isUserSubscribed~}}
  The user is subscribed to the broadcast by Email
  {{~else~}}
  The user is not subscribed to the broadcast by Email
  {{~/if~}}
{{else}}
No Email broadcast record found
{{/filter}}

Information Output from a smaller value to a larger one

The sortBy helper helps you sort from a smaller value to a larger one.

For example, using such a template, you can output the age from the age variable starting from the youngest and going up to the oldest:

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

In this template, array is an array of objects where we sort. Sorting here is performed by age variable.

In the sandbox, you can test this case using your own values.

Information Output from a larger value to a smaller one

The reverse helper helps you sort from a larger value to a smaller one.

For example, using such a template, you can output the age from the age variable starting from the oldest and going up to the youngest:

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

In this template, array is an array of objects where we sort. Sorting here is performed by age variable.

In the sandbox, you can test this case using your own values.

Add a certain number to all values of a variable

If you need to add, for example, number 500 to all the values in the list of the price variable, this template will do:

{{#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}}

Exclusion of empty lines from the list

In some cases, the bot may receive a list with empty lines. To get only filled items in the message, you can use this template:

<a name="empty">{{#each list}}
{{#if this}}
{{this}}
{{/if}}
{{/each}}
</a>

How to output multiple values from a string

This case is useful if you need to output the first few values that come from the beginning of a string with words separated by spaces. In our example, we have a string with names. We’ll output the first 5 names from it.

The number of output words must always be less than the number of words in the text, otherwise the template will not work.

The output of the required number of list items is as follows:

1. Cut the string into words by space and write the final list to the @vars.list local variable

2. Take all the list elements from the beginning to 5, tell the helper before how much is the indention from the end. We get this number by subtracting the number of list items that we need from the length of the list.

Write these elements to the sliced local variable.

3. After that, output it via join. This helper combines an array through a specific string. It is an empty string in our case.

As a result, we get such a template:

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

In the sandbox, you can test this case using your own values.

To the beginning ↑