Using Arrays in Calculations

What is an array?

Please note: this guide is intended for users who have some familiarity with calculations. If you’re new to this feature, we recommend starting with the Calculations Guide.

An array is kind of like a list—it’s a way to tell your calculation that you have some separate values that belong to a defined set. They’re great in any situation where you need to reference a group of items, and they have all sorts of practical applications.

For example, let’s say that you want to prohibit visitors to your form from entering email addresses that belong to certain domains. In your calculation, you could start by writing out an array containing all of the prohibited email domains.

prohibited = ARRAY( "gmail.com", "yahoo.com", "hotmail.com" );

Next, you would take the answer to an email question on your form, and use a bit of regex to extract the domain—everything after the “@” symbol.

prohibited = ARRAY( "gmail.com", "yahoo.com", "hotmail.com" );

domain = REGEXEXTRACT( {{ email_question_id }}, "@([a-zA-Z0-9-\\.]*)" );

Finally, if the customer’s email domain matches any of the items in your array, then your calculation could throw an error message telling them to use a different email address.

prohibited = ARRAY( "gmail.com", "yahoo.com", "hotmail.com" );

domain = REGEXEXTRACT( {{ email_question_id }}, "@([a-zA-Z0-9-\\.]*)" );

IF(
  INCLUDES( prohibited, domain ),
  ERROR( "Free-mail accounts are not allowed." ),
  "Looks good!"
);

In this case, the INCLUDES function checks each item in the prohibited array to see if any of them match the domain from the email answer. If it finds a match, then that function will resolve to true, which in turn triggers the error message.

Screenshot of an email question on the form, with "example@gmail.com" entered. A red error message appears below: "Free-mail accounts are not allowed."

Many functions are made to work with arrays in one way or another. In this guide, we’ll cover:

  • How to create arrays
  • Some common functions that work with arrays
  • How to use looping functions to simplify big tasks with lots of array items

We'll take a deep dive into a few specific functions; however, this is far from a complete list. Our full reference doc for functions can be found inside the calculation editor itself—just switch over to the "HOW TO USE" tab at the top.

Screenshot of the "HOW TO USE" tab of the Calculation Editor, within the form editor.

Specifically, the "LOOKUP" section contains many of the functions that utilize arrays.

Creating arrays

The ARRAY function

To create an array; simply list each item, separated by commas, inside of the ARRAY function.

ARRAY( "banana", "apple", "pear" )

In most cases, you’re going to want to save this array into a variable so that you can reference it later.

fruits = ARRAY( "banana", "apple", "pear" );

selected_item = {{ question_id }};

IF(
  INCLUDES( fruits, selected_item ),
  "You have selected a fruit.",
  "You have selected a vegetable."
);

If the live preview of your calculation result contains an array, it will be formatted in brackets. You will see each item separated by a comma, with no space between them. This can be helpful if you need to see what one of your arrays looks like, for testing and debugging down the road.

Screenshot of the calculation editor. The live preview shows an array: ["banana","apple","pear"]

The ARGS2ARRAY function

The ARGS2ARRAY function is similar to ARRAY. If you look them both up under “HOW TO USE,” you will notice a slight difference between their descriptions:

  • ARGS2ARRAY: Converts its arguments to an array.
  • ARRAY: Converts its arguments to a single, flattened array.

So, what does “flattened” mean in this case?

For advanced users who are comfortable with arrays, you may wish to create something called a multi-dimensional array; that is to say, an array that contains other arrays. This can be done using the ARGS2ARRAY function.

Let’s see what happens when we create two arrays and then combine them together, using only the basic ARRAY function:

Screenshot of the calculation editor. The ARRAY function combines two arrays into a single, flattened array.

At the end of this calculation, the individual values from both fruits and vegetables were combined into a single, flattened array with six total items; this now lives in the variable foods, exposed in the live preview in the screenshot above.

Next, let’s see what happens when we use ARGS2ARRAY for foods instead:

Screenshot of the calculation editor. The ARGS2ARRAY function combines two arrays to make a two-dimensional array.

Notice how this time, the foods array contains two smaller arrays? Nesting arrays like this can be handy in certain cases, but we won’t go over any uses of multi-dimensional arrays in this guide.

If you are a beginner, you’re probably going to want to stick to the ARRAY function. When you need to use more than one array in the same calculation, you can often get away with storing each one as its own variable.

The .array property

If you’re reading this guide, you should already know that a form's answers can be pulled into calculations using answer piping. However, you may not know that you can change the format or find a specific property of an answer using something called dot notation.

Multiple-choice and dropdown questions both feature the option to accept more than one answer. When multiple answers are selected, standard answer piping will combine the selections into a single string:

Screenshot of the calculation editor. The question key {{ 3j80r }} returns a string in the Live Preview: Choice 2, Choice 5, Choice 6.Screenshot of the calculation editor. The question key {{ 3j80r }} returns this in the Live Preview: Choice 2, Choice 5, Choice 6.

You can add the dot notation .array to return the selections as an array instead:

Screenshot of the calculation editor. The notated question key {{ 3j80r.array }} returns an array in the Live Preview: ["Choice 2","Choice 5","Choice 6"].

This comes in handy when you need to treat each selection as a separate value.

Utilizing arrays

The INCLUDES function

As mentioned earlier, INCLUDES searches an array for a specific value.

INCLUDES( array, value_to_search ) 

The function will return true if the value is found or false if it is not.

Screenshot of the calculation editor with the following calculation: fruits = ARRAY( "banana", "apple", "pear" );  INCLUDES( fruits, "apple" ); The live preview shows that the result is true.

This can be used in a couple of different ways. Using static values in the array, you could check to see if an answer from the form matches any value in your preset list:

fruits = ARRAY( "banana", "apple", "pear" );

INCLUDES( fruits, {{ question_id }} );

// returns true if the answer is either "banana", "apple", or "pear"

Alternatively, you may need to search through a dynamic array for a static value. Let’s try looking through all of the selected answers from our dropdown or multiple-choice question to find out whether a specific option was included:

answers = {{ question_id.array }};

INCLUDES( answers, "banana" );

// returns true if "banana" is one of the selected answers

INCLUDES also supports additional arguments, just in case you need to search for more than one item within the same array:

answers = {{ question_id.array }};

INCLUDES( answers, "banana", "apple" );

// returns true if both "banana" and "apple" are selected
// returns false if either or both are missing

When checking for multiple items, note that all items must be present in order for the function to return true. If you would like to find out whether any of those items are included in the original array, you can combine INCLUDES with OR instead like so:

answers = {{ question_id.array }};

OR(
  INCLUDES( answers, "banana" ),
  INCLUDES( answers, "apple" )
);

// returns true if "banana" or "apple" is selected (or both)
// returns false if both are missing

The SPLIT and JOIN functions

SPLIT and JOIN are a couple of useful functions for converting arrays to strings and vice-versa. Within a single calculation, you could SPLIT a string up into an array of multiple values, manipulate that array, and then JOIN the result back into a string.

Let’s start with SPLIT, which turns a string into an array.

SPLIT( text, separator )

The text here is the original string, while the separator indicates where the items should be split. The separator will also be removed from the resulting array.

fruits = "banana, apple, pear";

SPLIT( fruits, ", " );

// returns ["banana","apple","pear"]

JOIN does the same thing, but in reverse:

JOIN( array, separator )

In this case, the separator is the text to insert between each array item to build the string.

fruits = ARRAY( "banana", "apple", "pear" );

JOIN( fruits, ", " );

// returns "banana, apple, pear"

Don't forget about spaces! In both of the examples above, the separator is ", " as opposed to just "," (note the space after the comma). You’ll often want to remove spaces to create functional arrays from strings, or add spaces to create readable strings out of arrays.

GET, MATCH, and using indexes

The GET and MATCH functions make use of an array item’s index, which is a number that represents its position in the array. For example, the third item in an array would have an index of 3.

You can use GET to look up an array item by its index.

fruits = ARRAY( "banana", "apple", "pear" );

GET( fruits, 2 );

// returns "apple"

GET also accepts an optional third argument, which is a fallback value. This will be used if there is no item at the index requested.

fruits = ARRAY( "banana", "apple", "pear" );

GET( fruits, 5, "no fruit found" );

// returns "no fruit found"

If no fallback value is given and there is no item at the requested index, then GET will return an empty string.

fruits = ARRAY( "banana", "apple", "pear" );

GET( fruits, 5 );

// returns ""

The reverse of GET is called MATCH. This function will search an array for a specific item and return its index number.

fruits = ARRAY( "banana", "apple", "pear" );

MATCH( fruits, "apple" );

// returns 2

If the same item appears twice in the array, MATCH will return the index of the first item found (i.e. the lowest matching index).

fruits = ARRAY( "banana", "apple", "pear", "apple" );

MATCH( fruits, "apple" );

// returns 2

If the item isn’t found at all, MATCH will return 0.

fruits = ARRAY( "banana", "apple", "pear" );

MATCH( fruits, "pineapple" );

// returns 0

Other functions

The following functions are also commonly used with arrays:

  • FIRST, LAST, and SLICE pull specific item(s) from an array (similar to GET).
  • SET, PUSH, and UNSHIFT are used to add items to an array.
  • WITHOUT and UNIQUE are used to remove items from an array.
  • REVERSE changes the order of an array.
  • COUNT returns the number of items in an array.
  • COUNTNUMBERS, COUNTIF, and COUNTUNIQUE return the number of items that meet a certain condition.

Remember; for more info on each of these, look them up under “HOW TO USE” within the editor.

Screenshot of the "HOW TO USE" tab of the Calculation Editor, within the form editor.

Several more functions can work with arrays, even if aren’t described as such. For example, the instructions for AVERAGE show that each number should be its own argument:

AVERAGE( 7, 10, 11, 14 );

// returns 10.5

In actual practice however, this function will also accept an array:

values = ARRAY( 7, 10, 11, 14 );

AVERAGE( values );

// returns 10.5

If you’d like to use a “non-array” function like this with an array, give it a test—it might work!

Advanced array functions

Using expression strings

Paperform’s calculations don’t support fully customized loops to the degree that a programming language like Javascript or Python would. However, we do offer three special functions that can be used to repeat the same expression multiple times: once for each item in an array. These functions are called MAP, FILTER, and REDUCE.

  • MAP performs the same expression using each item in an array, and then returns a new array with the results.
  • FILTER checks each item in an array to see if it meets a certain condition, and then filters out those that don’t.
  • REDUCE combines all of an array’s items in a customizable way. Of the three advanced functions, this is the only one which does not return an array at the end.

These three functions are unique within Paperform in that they all require a special type of argument called the expression string. For example, here is the format for the function FILTER:

FILTER( array, expressionString )

The expression string is indeed a string (it should appear in quotes), and it contains the expression that will be repeatedly evaluated using each item of the array. In the case of FILTER, whether that expression returns true or false determines whether each item is filtered out. Here’s how you might use FILTER to remove every number in an array under 15:

Screenshot of the following calculation: scores = ARRAY( 145, 6, 13, 25, 7, 4, 400 );  FILTER( scores, "= item >= 15" );

We’ll explore FILTER in more detail later, but you can see at a glance how this works:

  1. The statement 145 >= 15 is true, and so 145 is included in the resulting array.
  2. The statement 6 >= 15 is false, and so 6 is filtered out.
  3. This process continues until all items have been evaluated, leaving us with a “filtered” array.

In short, you can think of an expression string kind of like the sub-task of the function. The functions MAP, FILTER, and REDUCE each utilize the expression string in a different way, so read on to find out which one is ideal for your use case.

Rules for expression strings

There are some special rules for expression strings:

  • The entire string should be in quotation marks.
  • The expression should start with an = sign.
  • The text item represents the current item in the array.
  • The text index represents the current item’s position in the array.
  • The text result represents the output from the previous evaluation (this is only used for REDUCE).

If this isn’t feeling totally clear yet, not to worry! In the following section, we’ll carefully break down two examples of the MAP function to explore how the expression string works.

The MAP function

MAP is the most straightforward of the three advanced array functions. It performs a certain expression using each item in an array, and then returns a new array containing each result.

For an example, let’s start with an array of numbers. We’d like to multiply each item by 10.

Screenshot of the following calculation: scores = ARRAY( 25, 30, 45 );  MAP( scores, "= item * 10" );

To understand how this works, let’s start by taking a closer look at the expression string:

"= item * 10"

To help you visualize this, you can imagine the result placed in front of the expression.

result_1 = item_1 * 10

Now, take a closer look at the original example. One by one, try plugging in each item in the array, and you can see how the results are calculated.

  1. 250 = 25 * 10
  2. 300 = 30 * 10
  3. 450 = 45 * 10

Expression strings can be extremely useful, but they can take a little getting used to. To make sure everything is clear so far, let's dig into this example a bit further. How could we accomplish the same task in a Paperform calculation without using MAP?

Let's break it down:

Screenshot of this calculation: scores = ARRAY( 25, 30, 45 ); score_1 = GET( scores, 1 ); score_2 = GET( scores, 2 ); score_3 = GET( scores, 3 ); result_1 = score_1 * 10; result_2 = score_2 * 10; result_3 = score_3 * 10; ARRAY( result_1, result_2, result_3 );

This longer calculation performs all of the same steps as our original example with MAP, however this time you can see it all laid out step-by-step. Notice this line from our expanded version:

result_1 = score_1 * 10;

See how similar it looks to the original expression string?

"= item * 10"

Our original example with MAP is actually doing all of the same work, except it only takes a fraction of the space.

Screenshot of the following calculation: scores = ARRAY( 25, 30, 45 );  MAP( scores, "= item * 10" );

Aside from cleaning up your code, these advanced array functions also offer a specific benefit: in actual practice, you may not know ahead of time how many items your array is going to have.

For example, imagine that you’re starting with an array containing the selected answers from a dropdown question. This question allows anywhere from two to five options to be chosen. We’d like to take these selections and make them all upper-case.

selections = {{ question-id.array }};

MAP( selections, "= UPPER( item )" );

Because we’re using MAP, this calculation is ready for an array containing any number of items.

Once you have a grasp on writing expression strings, the advanced array functions can become very powerful tools in your arsenal.

The FILTER function

FILTER is used to filter out items that don’t meet specific criteria.

Similar to MAP, FILTER asks for an expression string; this will be again be evaluated for each item in the original array.

FILTER( array, expressionString )

With FILTER, your expression string should always resolve to a Boolean value—that is, either true or false. When the result is true, the original item will be included in the final array. When false, that item will be removed. We’ve already gone over one example of this in an earlier section:

Screenshot of the following calculation: scores = ARRAY( 145, 6, 13, 25, 7, 4, 400 );  FILTER( scores, "= item >= 15" );

For our next example, let’s try something a little bit more complex. We’ll start with a long list of names and extract the ones that begin with the letter “B.”

Expression strings can (and often do) include other functions. In this case, we’re going to utilize the function LEFT, which pulls the leftmost character in a string.

LEFT( "Hello, world!" );

// returns "H"

Within our expression string, will use LEFT to find the first letter of each name. Then, we can check to see whether this letter is a “B”—this will either resolve to true or false, telling us whether or not to keep the name.

names = ARRAY(
  "Nathalie", "Alaric", "Greta",
  "Alejandro", "Christina", "Reese",
  "Reese", "Baker", "Maia",
  "Dallas", "Cali", "Preston",
  "Alondra", "Titus", "Maxine",
  "Stephen", "Meilani", "Jaxon",
  "Kamari", "Braylon", "Cali",
  "Omar", "Khaleesi", "Lennox",
  "Alexandria", "Bryson", "Queen",
  "Grey", "Ellie", "Blake"
);

FILTER( names, "= LEFT( item ) == 'B'" );

// returns ["Baker","Braylon","Bryson","Blake"]

This function uses LEFT( item ) to pull the first letter from each array item. If this first letter is equal to 'B' then the original item will be included in the final array.

If you have quotation marks inside of your expression string, make sure to switch from single to double quotes (or vice-versa) so that they don’t conflict with the ones surrounding the expression itself.

✅ "= LEFT( item ) == 'B'"
✅ '= LEFT( item ) == "B"' 
❌ "= LEFT( item ) == "B""

FILTER and MAP are two powerful tools for transforming an entire array. They allow you to work with groups of data without writing tons of code, and they also come in handy when you don’t know in advance how many items you’ll be working with.

Finally, let’s see how REDUCE utilizes the expression string in a different way.

The REDUCE function

Unlike MAP and FILTER, REDUCE does not return an array. Rather, this function is used to take the contents of an array and “reduce” everything down to a single item.

This function introduces a third keyword for our expression string (in addition to item and index). This time, result is used to represent the output from the previous iteration. Each time it runs, the expression will combine the previous result with the new item and/or index. This creates a new result to be used with the next array item, and so on. The final result is returned at the end.

REDUCE( array, expressionString, initialValue )

REDUCE also features a third argument, initialValue. This will be the starting value for result. If you omit the third argument, the initial value will default to 0.

We’ll start with a basic example using numbers:

scores = ARRAY( 25, 10, 14 );

REDUCE( scores, "= result - ( item * 10 )", 1000 );

// returns 510

Just as with the previous looping functions, our expression is evaluated once for each array item. The first time it runs, the result will equal our initialValue of 1000. Subsequent iterations will use each previous result. Let’s see how this breaks down in our case:

  1. First item: 1000 - ( 25 * 10 ) = 750
  2. Second item: 750 - ( 10 * 10 ) = 650
  3. Third item: 650 - ( 14 * 10 ) = 510

Our array only has three items, and so our REDUCE function returns the final result of 510.

For a different example, let’s try turning an array of strings into a numbered list. This will also be our first use of index, which we can use for the numbering in this case. Remember, index returns a number for the position of the item within the original array (the first item has an index of 1, the second has an index of 2, etc).

Screenshot of a calculation using RESULTS in the editor; the details are explained next in this guide.

This one is a little bit more complex, so let’s break it down step-by-step.

fruits = ARRAY( "banana", "apple", "pear" );

REDUCE(
  fruits,
  "CONCATENATE(
    result, IF( index == 1, '', '\n' ),
    index, '. ', item
  )",
  ""
);

We’ve set the initial value to ""; this sometimes called an empty string. Remember, the initial value defaults to 0, which wouldn’t be of much use to us in this case. Instead, an empty string starts us off with no text entered yet.

So, we will start off with a result of "", an index of 1, and the item "banana". Let’s zoom in on the expression string, and see how it looks with the first set of values filled in:

CONCATENATE(
  '', IF( 1 == 1, '', '\n' ),
  1, '. ', 'banana'
)

Note: CONCATENATE combines multiple strings of text into one. If a number is used as an argument, it will be treated as a string.

It looks like the condition for our IF statement is going to be true, leaving us with another empty string at the beginning. With that in mind, the result of this first iteration is:

"1. banana"

Next, let’s evaluate again for index 2. Plugging in the previous result along with the new index and item gives us:

CONCATENATE(
  '1. banana', IF( 2 == 1, '', '\n' ),
  2, '. ', 'apple'
)

This time, the IF’s condition is false, giving us the string "\n". This leaves us with something like:

"1. banana\n2. apple"

In calculations, "\n" is used to represent a line break. So, we're actually looking at something more like this:

1. banana
2. apple

We won’t see an index of 1 again after the first item, and so our expression will continue to add a line break with each iteration until the function has ended. In this case though, we’re almost done—the third and final iteration will leave us with:

"1. banana\n2. apple\n3. pear"

Which of course translates to:

1. banana
2. apple
3. pear

Putting it all together

Next steps

With this, you should have a solid basis for working with arrays. For a bit of additional context, we'll end with a few examples of practical applications. You can see additional uses for arrays and other calculation tools in our Calculations Cheat Sheet.

If you get stuck, feel free to reach out to our support team at support@paperform.co or by clicking the live chat icon in the bottom-right corner of any Paperform page.

Likert scale quiz

This type of quiz or survey gives weighted points based on answers along a range, like a Likert or semantic differential scale. While you can manually set this up with our built-in scoring, arrays offer a handy shortcut via MAP:

answers = ARRAY( {{ id-1 }}, {{ id-2 }}, {{ id-3 }} );

scores = MAP( 
  answers,
  "=SWITCH( item,
    'Never', 1,
    'Rarely', 2,
    'Sometimes', 3,
    'Often', 4,
    'Always', 5,
    0
  )"
);

SUMIF( scores );

If you prefer, the same thing can be accomplished with REDUCE:

answers = ARRAY( {{ id-1 }}, {{ id-2 }}, {{ id-3 }} );

REDUCE( 
  answers,
  "= result + SWITCH( item,
    'Never', 1,
    'Rarely', 2,
    'Sometimes', 3,
    'Often', 4,
    'Always', 5,
    0
  )"
);

Depending on how your questions are configured, there are a few alternative scoring methods that you could consider.

Select a random item from a list

Another example from the Calculations Cheat Sheet, this one utilizes a pseudo-random number to pull a random item from an array.

agents = ARRAY(
  "agent-1@example.com",
  "agent-2@example.com",
  "agent-3@example.com"
);

position = DATEFORMATUTC( NOW(), "X" ) % COUNT( agents ) + 1;

GET( agents, position );

For example, you may wish to assign each lead who submits your form to a randomized sales team member. You could use the calculation above to find a random salesperson's email, and then pipe the result into the "To" address of your custom email.

Combining two arrays

In certain situations, you might need to match up values from two arrays together. For example, let's say that you have one array of product quantities and another of product prices. You'd like to multiply each pair of array items together to find the totals for each product.

quantities = ARRAY( 50, 75, 20 );
prices = ARRAY( 10, 15, 20 );

MAP( quantities, "= item * GET( prices, index )" );

// returns [500,1125,400]

This utilizes a trick using GET inside of MAP. You can use the index of the current item in the "main" array to grab the item with the same index from the "secondary" array.

One practical use of this is a custom product order summary.

// --- enter all ID(s) & SKUs ---

SKUs = ARRAY( "sku-A", "sku-B", "sku-C" ); 

names = ARRAY(
  {{ id.names.sku-A }},
  {{ id.names.sku-B }},
  {{ id.names.sku-C }}
);

quantities = ARRAY(
  {{ id.quantities.sku-A }},
  {{ id.quantities.sku-B }},
  {{ id.quantities.sku-C }}
);

prices = MAP(
  ARRAY(
    {{ id.prices.sku-A }},
    {{ id.prices.sku-B }},
    {{ id.prices.sku-C }}
  ),
  "= FIXED( item, 2 )"
);

selected = {{ id.selectedProducts }};

// --- build the summary ---

totals = MAP( prices,
  "= FIXED( NUMBERVALUE( item ) * GET( quantities, index ), 2 )"
);

summary = MAP( selected,
  "= CONCATENATE(
    GET( names, MATCH( SKUs, item ) ),
    ' ($',
    GET( prices, MATCH( SKUs, item ) ),
    ') x ',
    GET( quantities, MATCH( SKUs, item ) ),
    ' = $',
    GET( totals, MATCH( SKUs, item ) )
  )"
);

JOIN( summary, "\n" );

General tips for advanced array functions

Writing out functions with expression strings can start to feel pretty Inception-like pretty quickly. To keep it all straight, we recommend making sure that the expression string works on its own before fitting it into MAP, FILTER, or REDUCE.

Let's take another look at one of our earlier example functions. Back in the FILTER section, we extracted names that start with a "B" out of a longer list.

names = ARRAY(
  "Nathalie", "Alaric", "Greta",
  "Alejandro", "Christina", "Reese",
  "Reese", "Baker", "Maia",
  "Dallas", "Cali", "Preston",
  "Alondra", "Titus", "Maxine",
  "Stephen", "Meilani", "Jaxon",
  "Kamari", "Braylon", "Cali",
  "Omar", "Khaleesi", "Lennox",
  "Alexandria", "Bryson", "Queen",
  "Grey", "Ellie", "Blake"
);

FILTER( names, "= LEFT( item ) == 'B'" );

// returns ["Baker","Braylon","Bryson","Blake"]

Writing this out from scratch from top-to-bottom would be way too confusing. Instead, we had to build it from the inside out, beginning by isolating the expression string.

The first thing that our expression needs to do is find the first letter of each name. Forget arrays for a moment—how would we do this for a single value?

Screenshot of the following calculation: test_item = "Nathalie"; LEFT ( test_item ) == "B";Screenshot of the following calculation: test _item = "Nathalie"; LEFT ( test_item );

Next, we'll need to check to see if that letter is a "B" or not. Remember, FILTER is going to need Booleans later on (true/false).

Screenshot of the following calculation: test_item = "Nathalie"; LEFT ( test_item ) == "B";

This is returning false for "Nathalie" as expected. Let's test it out with a "B" name too, just to make sure that we also get true when we're supposed to.

Screenshot of the following calculation: test_item = "Baker"; LEFT ( test_item ) == "B";

At this point, we can be fairly confident that our expression works. Now, we are finally ready to turn what we have so far into an expression string for FILTER, being careful about single- and double-quotes.

Screenshot of the following calculation: names = ARRAY( "Nathalie", "Alaric", "Greta", "Alejandro", "Christina", "Reese", "Reese", "Baker", "Maia", "Dallas", "Cali", "Preston", "Alondra", "Titus", "Maxine", "Stephen", "Meilani", "Jaxon", "Kamari", "Braylon", "Cali", "Omar", "Khaleesi", "Lennox", "Alexandria", "Bryson", "Queen", "Grey", "Ellie", "Blake" );  FILTER( names, "= LEFT( item ) == 'B'" );

Notice that even at this point, we're still using test values for everything—we haven't done any answer piping yet. It's always a good idea to work out the logic of your calculation entirely using static values like this first. That way, you can test it out in real time by entering different values and watching the results change in the live preview.

Everything is looking good so far, and so we are finally ready to start pulling in the actual answers from the form that we want to use.

Screenshot of the following calculation:  names = ARRAY( {{ e7jcq }}, {{ er441 }}, {{ 1kobk }} );  FILTER( names, "= LEFT( item ) == 'B'" );

Our next step after this would be to make the calculation field visible and test it out further by previewing the form. Select or enter different answers, and then watch the calculation's result change right there on the form. This is a convenient way to test out the "real" calculation without actually submitting. If it all works, then you're ready to hide the calculation again (if desired) and move on.