Collections (AKA Arrays or Lists) 🔗
A collection is a grouping of items, all saved under the same variable name. You can create a collection from scratch like this:
>> myCollection = ["thing 1", "thing 2", "thing 3"]
When checkbox responses are saved, they're saved in what's called a collection, which could look something like this:
["Dog", "Cat", "Hamster/other small furry thing"]
All you need to do to save checkbox responses into a collection
is add the
*save
keyword. For example, imagine we asked users to check off which
pets they had and saved their responses as
pets
.
*question: Which of the following pets do you have?
*type: checkbox
Dog
Cat
Hamster/other small furry thing
Fish
Leopard, lion, panther
None of the above
You can use the
in
expression to provide special content to users who checked off a
certain item. If we then wanted to give a follow-up question to
users who had checked off "Cat," we could do the following:
*if: "Cat" in pets
*question: Are you a crazy cat person or just a normal cat person?
Normal
Crazy
Very crazy
Similarly, you can use
not
to add special content for those who don't have a certain item
in the collection:
*if: not "Cat" in pets
Here's a reason you should get a cat: "The smallest feline is a masterpiece." - Leonardo da Vinci
Capitalization and punctuation are important when using
in
expressions. Writing "cat" in lowercase would not have worked.
Now, we're going to delve even deeper into collections. This functionality is essential for complex programs like the following:
- You want to store each answer that a user provided to a repeated question
- You want to combine a user's answers from two or more questions into one variable
- You need to alphabetize a list of things
- You need to get the mean of a list of things
- You need to know the size of a list of things
Getting and using a specific item in a collection 🔗
Let's suppose you have a collection of numbers that looks like this:
>> mood_scores = [6, 8, [4, 3, 5]]
We'll pretend these represent a person's mood scores (how they
felt on a scale of 1-10) across time. Notice how collections can
contain collections within them (as the third position in this
collection does). For now, just imagine that the mood scores of
the third position
[4, 3, 5]
are clumped together because they were all collected on the same
day.
There are several ways the program can use collections to interact with the user. You can simply show the user their collection:
Your mood scores were {mood_scores}.
This would produce a line of text that looked like this to the user:
You can also show the user specific entries in their entire collection. In our example, we want to show the user the first and second things in their collection:
Your first ever mood score was {mood_scores[1]}.
Your second score was {mood_scores[2]}.
Users would see the following:
You can also show users a specific entry of a collection within a collection:
Yesterday, you said {mood_scores[3][1]}, then {mood_scores[3][2]}, and finally {mood_scores[3][3]}.
With the above code, users would see the following:
Collection entries can be used similarly as other variables. For example, you can do the following things:
*if: mood_scores[1] >= 7
You started with a pretty good mood.
*repeat: mood_scores[2]
:-)
In the first example, if the user's first mood score in their collection were a 7 or above, they'd see "You started with a pretty good mood." In the second example, users would see as many smiley faces as their mood rating. In this case, they'd see 8 smiley faces.
Looping through all the elements of a collection 🔗
Use the
*for
keyword to go through all the elements of your collection. For
example, when you run this code:
>> farmAnimals = ["dog", "pig", "goat"]
*for: animal in farmAnimals
*header: There is a {animal} on the farm!
this is what will be displayed:
This is because the code indented under the
*for
keyword is executed as many times as there are elements in the
collection
farmAnimals
(3 in the example). On each iteration,
animal
will be the element on the position of the current iteration.
There may be cases where you want to store also the iteration number. Look at the example below:
>> highestPeaks = ["Everest", "K2", "Kangchenjunga"]
Here are the *highest mountains* on Earth:
*for: index, name in highestPeaks
*header: {index}. {name}
The
*for
loop will go through the collection
highestPeaks
, setting
index
to the iteration number and
name
to the element in that position. This is what the output looks
like:
In summary, when you are using
*for
to loop through the elements of a collection, you can either
retrieve each of the elements in it using the syntax
*for: element in collection
or both the element and its position if you write
*for: position, element in collection
.
The keyword
*for
is super useful when you have your user's answers stored in a
collection and you want to generate the same question for each
of their answers. Suppose you have a program where the user has
been asked to enter their favorite restaurants, which are stored
in the collection
favRestaurants
. Asking what is their favorite food at each of those
restaurants is this easy:
*for: restaurant in favRestaurant
*question: What is your favorite food at {restaurant}?
Get the size of a collection 🔗
Getting the size of a collection is pretty easy. Using our earlier pet example, we could say:
You have {pets.size} different kinds of pets.
This would then say "You have 3 different kinds of pets" because our pets collection contained a dog, cat, and a small furry thing.
Get the mean value of a collection of numbers 🔗
If you have a collection of numbers, such as
[10, 10, 30, 30]
, you can easily find the mean of the collection, like this:
The mean of these values is: {yournumbers.mean}.
This would read as "The mean of these values is: 20."
Add something to the end of a collection 🔗
Adding new items to a collection is pretty easy. If you have a
collection called
user_badges
, you could add a new entry to the collection like so:
>> user_badges.add("Topped 1,000 points")
The new entry, "Topped 1,000 points," would be added to the end
of the collection called
user_badges
.
Now let's use a more complicated example about a question that asks users to painstakingly enter 50 hobbies. Here, the collection is initially empty.
>> hobbies = []
*repeat: 50
*question: Enter one of your hobbies.
*save: newHobby
>> hobbies.add(newHobby)
Great! Now add another
Here are the hobbies you listed: {hobbies}
First, we have to set up the collection that the user's answers
will go into. We've written
>> hobbies = []
at the top. Initially, it's an empty collection, but it will
soon fill up with user data.
Users will next see "Enter one of your hobbies" and can enter
whatever they like in the box. Their answer is saved as the
variable
newHobby
. Then, this variable is added to the end of the collection
called
hobbies
. Since the collection is empty in the beginning, the first
answer users provide will momentarily be the only thing in the
collection. The user will next see "Great! Now add another" and
the question will reappear. Users will repeat the process of
typing in each new hobby for a total of 50 times. Each time, the
variable
newHobby
will change to the latest thing they wrote and this thing will
be added to the end of the user's collection. When users are
finished, they will see "Here are the hobbies you listed:"
followed by all 50 of the hobbies they typed.
You'll notice that in the
user_badges
example what's called a
text string
was added to the collection ("Topped 1,000 points") and in the
second example the value of a variable was added (
newHobby
). In all aspects of GuidedTrack, there are three different
types of information you can store and work with:
- text strings
- numbers
- collections
There are also variables, which store any of the three types. Here's how a text string, a number, and a collection look:
>> hobbies.add("lawn mowing")
>> hobbies.add(2048)
>> hobbies.add([newHobby, "lawn mowing", 2048])
Here's how a variable looks:
>> hobbies.add(newHobby)
Insert something in a specific point in the collection 🔗
When you add something to a collection, it gets added to the very end of the collection. But what if you want to insert something at a very specific spot of the collection? You'd do so like this:
>> hobbies.insert("lawn mowing", 3)
This inserts "lawn mowing" as the 3rd thing in the hobbies collection. Within the parentheses, the first part is always the thing you want to insert. The second part is the position that you want to insert the thing in.
In this next example, the user's answer has been added to the beginning of their collection.
*question: What's your favorite hobby?
*save: favorite
>> hobbies.insert(favorite, 1)
Your favorite hobby is listed first: {hobbies}
Sort a collection 🔗
It's pretty easy to sort a collection so that all the entries
are in increasing order:
(a, b, c, ..., 1, 2, 3)
or decreasing order
(9, 8, 7, ..., z, y, x)
.
>> hobbies.sort("increasing")
Here are your hobbies alphabetized: {hobbies}
>> hobbies.sort("decreasing")
Here are your hobbies listed from z to a: {hobbies}
Sorting is also very handy for collections of numbers. It can be used to put all the numbers in either increasing or decreasing numerical order.
Shuffle around a collection 🔗
Similarly, you can sort the items in a collection so they're in a completely random order:
>> hobbies.shuffle
Here are your hobbies in a totally random order: {hobbies}
Combine two or more collections 🔗
Let's say you have two collections and you want to combine them into one collection. We'll use these two as an example:
>> listA = [5, 8, 22]
>> listB = [7, 23, 6, 4]
In order to add the items of
listB
into
listA
, you'd use the following code:
>> listA.combine(listB)
Your list: {listA}
In the above example,
listB
would still contain its original 4 items, but
listA
would now have 7 items (its original 3, plus the 4 from
listB
). If you were to show
listA
to users it would look like this:
Let's imagine the variable
listB
didn't actually exist. You can still add these new numbers to
listA
like so:
>> listA.combine([7, 23, 6, 4])
Making a duplicate of a collection 🔗
Suppose you have a list that you're going to make changes to,
and you want to save a copy of its value before making the
changes. If you simply do
listB = listA
, you will notice that whatever changes you make to
listA
also show on
listB
, which defeats the purpose of doing that! This is not a bug;
you can find a more detailed explanation of this behavior (and
why it may be useful sometimes!)
here
.
In order to create a new collection that takes the current values of an another one, do this instead:
>> listB = []
>> listB.combine(listA)
Next: Components