Syntax Guide: Multi-select questions

November 30, 2016

Two types of multi-select questions

There are two types of multi-select questions. They differ not only in the way they appear, but in the way their answers can be referenced with Survey Solutions’ conditions language.

Click below on the type of multi-select question that interests you:

Series of tick boxes

Technical introduction

When the interviewer answers a multi-select question, the answers are stored in an array.

To make this abstract statement more concrete, take an example.

In the figure, the selected items are: maize (1) and ground bean (27).

Thus, the array of answers can be represented in this way:

    ag_d20 = {1,27}

Where the array contains the values of the items selected–that is 1 and 27

Common tasks

Find a particular value

  • Contains. Checks whether the answers to question contain a specified value.
  • ContainsOnly. Contains only the specified value

Look for several values

  • ContainsAll. Check whether the answers contain all of the specified values.
  • ContainsOnly. Contains only the specified values
  • ContainsAny. Contains at least one of the specified values
  • !ContainsAny. Contains none of the specified values. See the second example of ContainsAny

Count the number of values

  • Length. Computes the number of answers to a multi-select question.

Syntax explained

Contains

Syntax

    tickBox.Contains(a)

Description

Checks whether the value a is among the answers to a tickBox–that is, is contained in the set of answers. Returns true if a is contained in tickBox’s answers. Returns false otherwise.

Example

Often, the questionnaire designer wants to trigger certain behavior if a particular answer option is among those selected. In the example below, the interviewer needs to write a text description for the use of a loan/credit if “other (specify)” is one of the three answers recorded.

 

To put this in terms closer to the programming language solution, the questionnaire developer enables a text question if the code for “other (specify)” (10) is contained in the array of answers to the multi-select question. In code:

    // enable text field to specify if "other" selected (among potentially other options)
    hh_p10.Contains(10)

ContainsOnly

Syntax

Single-value version:

    tickBox.ContainsOnly(a)

Multiple-value version:

    tickBox.ContainsOnly(a,b,c,...)

Description

Checks whether the value a (a,b,c,…) is (are) the only answer(s) to tickBox. Returns true if a (a,b,c,…) is (are) the only answer(s). Returns false otherwise.

Example

With multi-select questions, multiple answers are allowed. However, in some cases, two (or more) answers cannot be (logically) selected at the same time. That is, some answers may be mutually exclusive.

Consider the example below where the answer set includes several sources for start-up capital as well as “No start-up cost”.

Clearly, if “No start-up cost” is selected, some other option cannot also be selected. The contrapositive is also true: if a non-“No start-up cost” option is ticked, “No start-up cost” cannot also be ticked.

Translating intention to code, we can describe the valid set of answers to this multi-select question:

    // either "No start-up cost" not selected...
    !hh_n08.Contains(13)

    ||

    // ...or "No start-up cost" is the only answer provided
    hh_n08.ContainsOnly(13)

Note: ContainsOnly also allows either a single value or multiple values to be specified. We leave to the reader the task of finding an appropriate example for using the multi-value version of ContainsOnly

ContainsAll

Syntax

    tickBox.ContainsAll(a,b,c,...)

Description

Checks whether the values a,b,c,… are all contained in the set of answers to tickBox. Returns true if a,b,c,… are all selected answers to tickBox. Returns false otherwise.

Example

Using Contains allows one to determine whether a certain answer is contained in a multi-select question’s array of answers.

To check for more than one answer, one would need to write something like the following

    // the multi-select contains answers 4 and 5
    multiSelect.Contains(4) && multiSelect.Contains(5)

To do the same in more compact form, one could also write the following:

    // the multi-select contains all of the listed answers: 4 and 5
    multiSelect.ContainsAll(4,5)

ContainsAny

Syntax

    tickBox.ContainsAny(a,b,c,...)

Description

Checks whether any of the values a,b,c,… are contained in the set of answers selected for tickBox. Returns true if any of a,b,c,… are contained in tickBox’s answers. Returns false otherwise.

Example

Sometimes, the questionnaire designer wants to implement the same behavior when one of several answers is selected–that is, if any element in a list of answers is contained in a multi-select question’s array of answers.

To make this abstract situation concrete, consider the excerpt from an agricultural questionnaire below.

Looking at the list of answer options, it is clear that the interviewer must specify a crop whenever an “other” option is selected. Several crops have other options: tobacco (10), groundnuts (16), rice (26), and other crops (48).

To do this, the there are two options. The first option:

    // enable a text question if any "other" option is selected
    crops.Contains(10) ||
    crops.Contains(16) ||   
    crops.Contains(26) ||
    crops.Contains(48)

The expression is valid. It does what we want. But it is inelegant and error-prone to write

The second option:

    // enable a text question if any "other" option is selected
    crops.ContainsAny(10,16,26,48)

This solution is more compact, more readable, and less prone to error.

Length

Syntax

    tickBox.Length

Description

Determines the length of the array of answers–that is, the count of answers selected for tickBox.

Example

The length of a tick-all-that-apply, multi-select question yields the number of ticked answers.

While this information may not seem immediately practical, it often can be surprisingly useful. For some questions, the number of answers may useful in writing enablement or validation conditions.

Consider the questionnaire excerpt below:

Logically, the questionnaire developer wants either “no start-up cost” to be selected, or some other answer option–but never the two things at the same time. Earlier, we saw how to write this expression. Below, we revisit this example using the Length property of a multi-select question.

Using Contains and ContainsOnly, we wrote:

    // either "No start-up cost" not selected...
    !hh_n08.Contains(13)

    ||

    // ...or "No start-up cost" is the only answer provided
    hh_n08.ContainsOnly(13)

Using Length we can write something similar:

    // if a single answer is selected, it can be any option
    hh_n08.Length==1

    ||

    // if more than 1 answer is selected, the set of answers cannot contain "no start-up cost"
    (hh_n08.Length>1 && !hh_n08.Contains(13))

Series of yes/no questions

Technical introduction

This type of question consists of items, and for each item of a “yes”, “no”, or missing answer.

When the interviewer answers an item, the data are stored in the following way. For each state of an item’s answer, there is an array. In each array, one finds value of the item(s) with that state. In other words, there are the following arrays, with the following contents:

  • Yes. Contains the values of items with a “yes” answer.
  • No. Contains items with a “no” answer.
  • Missing. Containts the items without an answer–that is, without a “yes” or “no” answer. Before any item is answered, all items are in the Missing array. As items obtain “yes” or “no” answers, they move to the Yes or No array.

In addition to these three arrays, there is also an array All that containts the values of all items, whatever each item’s status.

To make things more clear, consider the following example.

In the image above, all items are answered with a “yes” or “no”. The “yes” answers are: Mortar/pestle (501), Bed (502), Chair (504), and Radio (507). The “no” answers are: Table (503), Fan (505), Air conditioner (506), Tape or CD/DVD player;HiFi (508), Radio with flash drive/micro CD (5081).

Hence, the arrays are:

    hh_l01.Yes = {501,502,504,50
    hh_l01.No = {503,505,506,508,5081}
    hh_l01.Missing = {}
    hh_l01.All = {501,502,503,504,505,506,507,508,5081} 

The items with a “yes” answer appear in the Yes array, those with a “no” in No, and the Missing array is empty, since all items were answered in this example

Common tasks

Find a particular value

  • Contains. Checks whether the answers to question contain a specified value.
  • ContainsOnly. Contains only the specified value

Look for several values

  • ContainsAll. Check whether the answers contain all of the specified values.
  • ContainsOnly. Contains only the specified values
  • ContainsAny. Contains at least one of the specified values
  • !ContainsAny. Contains none of the specified values. See the second example of ContainsAny

Count the number of values

  • Length. Computes the number of answers to a multi-select question.

Syntax explained

Contains

Syntax

    yesNo.ArrayName.Contains(a)

Where yesNo is the variable name of a Yes/No mode mutli-select question, and ArrayName is the name of the Yes/No mode arrays (see the technical introduction for more).

Description

Checks whether the value a is among the values in the array ArrayName for the question yesNo. Returns true if a is contained in yesNo’s ArrayName. Returns false otherwise.

Example

In excerpt below, the designer wants to capture a text description if a “Yes” answer is recorded for the “Other, specify” item.

 

Let’s think how this could be accomplished. First, one would need to know the code of the “Other, specify” item. Let’s assume this is 4. Then, one would need to know the where “Yes” answers are stored for Yes/No mode multi-select questions. According to the technical introduction, this is an array named Yes that is associated with any Yes/No mode, multi-select question.

Putting together these pieces,

    // if the Yes array for question 19 contains "Other, specify", then enable this question
    hh_n21.Yes.Contains(4) 

ContainsOnly

Syntax

Single-value version:

    yesNo.ArrayName.ContainsOnly(a)

Multiple-value version:

    yesNo.ArrayName.ContainsOnly(a,b,c,...)

Where yesNo is the variable name of a Yes/No mode mutli-select question, and ArrayName is the name of the Yes/No mode arrays (see the technical introduction for more).

Description

Checks whether the value a (a,b,c,…) is (are) the only answer(s) in the array ArrayName assocatiated with the multi-select question yesNo. Returns true if a (a,b,c,…) is (are) the only answer(s). Returns false otherwise.

Example

If the questionnaire designer wants only certain items to have “yes” or “no” answers, they may use ContainsOnly.

    // ensure that only item 105 has a "no" answer
    yesNo.No.ContainsOnly(105)

ContainsAll

Syntax

    yesNo.ArrayName.ContainsAll(a,b,c,...)

Where yesNo is the variable name of a Yes/No mode mutli-select question, and ArrayName is the name of the Yes/No mode arrays (see the technical introduction for more).

Description

Checks whether the values a,b,c,… are all contained in the array ArrayName associated with the multi-select question yesNo. Returns true if a,b,c,… are all selected answers to yesNo. Returns false otherwise.

Example

Suppose that the questionnaire designer wants to implement a validation rule about how tables and chairs are owned. The rule is as follows. If the household owns a chair, they may or may not own a chair. If the household owns a table, then they must also own a chair. A household never owns a table with a chair.

To move one step closer to implementation, let’s translate this intent into pseudo-code. If the code for “chair” appears in the Yes array, then “table” may also. If the code “table” apepars in the Yes array, then “chair must also appear. And it is possible that neither item appear in the Yes array.

Moving from pseudo-code to code,

    // either table and chair are owned together...
    hh_l01.ContainsAll(503,504)

    ||

    // ...or a chair is owned without a table...
    hh_l01.Contains(504) && !hh_l01.Contains(503)

    ||

    // ...or neither a table nor chair is owned
    !hh_l01.ContainsAny(503,504)

ContainsAny

Syntax

    yesNo.ArrayName.ContainsAny(a,b,c,...)

Where yesNo is the variable name of a Yes/No mode mutli-select question, and ArrayName is the name of the Yes/No mode arrays (see the technical introduction for more).

Description

Checks whether any of the values a,b,c,… are contained in the ArrayName associated with the Yes/No mode question named yesNo. Returns true if any of a,b,c,… are contained in yesNo’s answers. Returns false otherwise.

Example

Consider the following questionnaire excerpt:

Suppose that one wants to check that recorded asset ownership makes sense. In particular, the following rule: if a household owns basic assets, then they may or may not own luxury assets; if the household owns luxury assets, they must also own basic ones; and luxury assets cannot be owned without also owning basic assets.

For this example, basic assets can be considered as the following: mortar (501), bed (502), table (503), chair (504). Luxury goods can be considered to be: fan (505), air contioner (506), and radio (507). That is, basic assets can be any of a certain set, and luxury assets any of another set.

Using ContainsAny, one can write:

    // if has basic assets, may have luxury assets...
    ( hh_l01.Yes.ContainsAny(501,502,503,504) && hh_l01.Yes.ContainsAny(505,506,507) )

    ||

    // ... or may not have basic assets
    ( hh_l01.Yes.ContainsAny(501,502,503,504) && !hh_l01.Yes.ContainsAny(505,506,507) )

Length

Syntax

    yesNo.ArrayName.Length

Where yesNo is the variable name of a Yes/No mode mutli-select question, and ArrayName is the name of the Yes/No mode arrays (see the technical introduction for more).

Description

Determines the length of the the array ArrayName associated with the question named yesNo–that is, the count of items in ArrayName.

Example

Suppose that a questionnaire designer wants to ensure that food consumption information is properly recorded by interviewers. In particular, the designer believes that surveyed hosueholds, however poor, they will consume at least one cereal or cereal product in the last 7 days.

To do this, one needs to count the number of “yes” answers, and make sure that the count is greater than or equal to 1. In code:

    // however poor the household, at least one food has a "yes" answer
    hh_j01.Yes.Length>=1