to class -- to about -- to syllabus -- to people -- to the library

work session

tutorial: arrays and objects tips n tricks

Let’s recap:
All of you by now (yes, you!) have collected an array of objects. Each of your objects in your object-arrays has a number of properties. Some of these properties are equal to strings (like 'potato' or 'In the end, I knew that I was in love with his pot-plants, more than I was in love with him...'), some are numbers (like 5), some are equal to arrays (like ['spoons', 'spoons', 'spoons']), and some are equal to yet more objects, with their own properties, etc etc.

We know that we can

Objects are great for:

Arrays are great for:

Thus, arrays of objects are good for:

A reminder of the requirements for your final project:

In this class, I’ll go through a bunch of array tips and tricks that will allow you to very effectively manipulate your elements! We’ll be using our old friend, the fruit array:

var fruits = [
	{
		"name": "blueberry",
		"color": "blue",
		"flavor": "tart",
		"shape": "round"
	},

	{
		"name": "banana",
		"color": "yellow",
		"flavor": "sweet",
		"shape": "curved"
	},

	{
		"name": "pineapple",
		"color": "yellow",
		"flavor": "tangy",
		"shape": "columnar"
	},
]

picking random elements from arrays

We want a random fruit! Let’s recall array.length, the array method that lets us get the length of any array. What’s nice about this is that it works however many elements are in the array, so you can avoid having to hard-code values (important for your final project’s third requirement).

If we want to pick a random fruit, what we really want to do is randomly pick an index in our array that’s somewhere between 0, and the length of fruits.

If we use Math.random(), this will give us a random number between 0 and 1. If we multiply Math.random() by fruits.length, this will give us a random number betwee 0, and the length of fruits. This is pretty good, but it’ll give us a decimal (called a float in code-speak) where we want a whole number. We also want to round down, as we don’t want the actual length of the array, as the elements start from 0.

So, to put it all together:

var randomFruit = fruits[Math.floor(Math.random()*fruits.length)]

finding things in arrays

array.includes

Check if an array includes an element. Note that you have to use the exact value of the element you’re trying to select.

var fruit = {
	"name": "blueberry",
	"color": "blue",
	"flavor": "tart",
	"shape": "round"
},

var fruitName = "blueberry"


fruits.includes(fruit) //true
fruits.includes(fruitName) //false

array.indexOf

This gives us the location of an element in an array

var fruit = {
	"name": "blueberry",
	"color": "blue",
	"flavor": "tart",
	"shape": "round"
},

fruits.indexOf(fruit) //0

array.filter

What if we wanted to find objects with a particular property in an array? We’d want to use array.filter (array.includes is gonna match the whole thing, not part of the thing).

These are in the notes from last class too:

var filteredArray = fruits.filter(fruit => fruit.color === 'yellow');

This uses something called an arrow function, which is short and sexy, but we can also happily write it like this:

var filteredArray = fruits.filter(function(fruit){ return fruit.color === 'yellow' });

In both cases, filteredArray is a new array that contains just the entries for which the statement was true.

doing something to each element in an array

We know from a few classes ago now about the for loop, which is a nifty beast that is 1) totally correct and valid Javascript, and 2) universally usable. forEach is a slightly more lightweight way of doing the same job, but I’ll stress that everything that can be done with forEach, and more, can be done with a for loop. Your code will get much shorter though.

The thing with forEach’s syntax is that, unlike in a for loop, you’re creating a new variable, and that variable stores one element of an array at a time, not a whole array.

So, if i have an array fruits = [apple, banana, orange] , and I write the following:

fruits.forEach(function(fruit){
    console.log("I like " + fruit.name)
})

In other words, fruit here stores the value of each array element in turn, then the forEach loop runs code on them. Will print the name of each element in turn. What I call the variable will not change how the function works!!

selecting parts of arrays

If we want to copy a part of our array, we can use the array.slice() method. This will copy from a beginning index, to an end index (which, if not specified, will automatically be the end of the array).

var fruits2 = fruits.slice(0) // gets the whole array
var fruits3 = fruits.slice(1, 2) //gets the elements from 1 to 2
var fruits4 = fruits.slice(-1) // gets the last element in the array

sorting things in arrays

The sort function is pretty neat, but takes a bit of getting used to. It’s probably the most complicated thing we’ll cover today. What I would say is that it makes most sense in cases where you have some numerical value, or you’d like to sort things in alphabetical order. Sorting by things where the category is otherwise quite subjective (e.g. “I’d like to sort these by colour in order of the rainbow”). One way to get around this is, if you have multiple metrics along which you’d like to sort your objects, give each object a numerical value.

For example, I’d like to sort my fruit by deliciousness. This is obviously subjective (we’d all come up with different answers, let alone a poor browser), so I will add in some scores to help us along:

var fruits = [
	{
		"name": "blueberry",
		"color": "blue",
		"flavor": "tart",
		"shape": "round",
		"deliciousness": 6
	},

	{
		"name": "banana",
		"color": "yellow",
		"flavor": "sweet",
		"shape": "curved",
		"deliciousness": 8
	},

	{
		"name": "pineapple",
		"color": "yellow",
		"flavor": "tangy",
		"shape": "columnar",
		"deliciousness": 10
	},
]

Syntax:

The simplest way to use sort is to use its default functionality: simply array.sort()

const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]

const numbers = [1, 30, 4, 21, 100000];
numbers.sort();
console.log(numbers);
// expected output: Array [1, 100000, 21, 30, 4]

Notice that the second output doesn’t get sorted in terms of the value, but just the number it started with. This will be no good for our fruits array! It’ll score pineapple the lowest, when it is clearly the highest-tier fruit. eugh (we also have an array of objects!)

However, we’re also allowed to make up our own sorting rules, instead of following the default ones. Like filter, this way of thinking can take a little bit of getting used to. We’re going to run a small function inside the sort, and whatever that function returns for two adjacent elements of the array will determine what order they come in:

array.sort(comparisonFunction(a, b))

The rules (from Mozilla):

So: what if we wanted to sort our items numerically?

Let’s put this into practice to get a real numerical sort on our fruits:

//sort by deliciousness
fruits.sort(function(a, b) {
  if (a.deliciousness > b.deliciousness) {
    return 1;
  }
  if (a.deliciousness < b.deliciousness) {
    return -1;
  }
  return 0;
});

If fruit a is more delicious then fruit b, it’ll get bumped up the array. If it’s less delicious, it’ll get bumped down. And, if neither of these things are true, it’ll retain the same position.

We can actually write this out in a much shorter way using an anonymous function

fruits.sort(function(a, b){ return a - b })

Here, if a > b, it’ll return > 0 (so a will get bumped up). And vice-versa for a < b.

If we wanted to sort alphabetically (e.g. by name, or another string property), we still use > and < symbols (lol, JS), though we can no longer use subtraction.

//sort alphabetically
fruits.sort(function(a, b) {
  if (a.name > b.name) {
    return 1;
  }
  if (a.name < b.name) {
    return -1;
  }
  return 0;
});

adding elements to arrays

This is pretty simple and sweet (sort now seems like an unpleasant fever dream…)

I have another fruit, and I want to stick it onto the end of my array:

var papaya = {
	"name": "papaya",
	"color": "orange",
	"flavor": "delicate",
	"shape": "squash shaped",
	"deliciousness": 9
}

To add it to fruits, I simply do:

fruits.push(papaya)

Question for the audience: did the variable have to be called papaya?

removing elements from arrays

Removing elements from arrays is always a little tricky to remember, as there is not actually a dedicated function to remove a single element from an array. array.delete is probably not your friend here!!! It will remove the value of and information about that element, but it will leave an empty space in the array, and it won’t change the index of any of the other elements.

The method you probably want to use is splice (not to be confused with slice)! Say I wanted to rid the following array of the element "kiwi". First, I need to find where "kiwi" is located, for which I’m going to use fruits.indexOf, like above:

var fruits = ["apple", "banana", "pear", "kiwi", "orange", "plum"]
var index = fruits.indexOf("kiwi")

What happens when we delete?

fruits.delete(index)

///this gives us ["apple", "banana", "pear", undefined, "orange", "plum"]

To remove, we use:

fruits.splice(index, 1)

///this gives us ["apple", "banana", "pear", "orange", "plum"]

This removes 1 element, from the position in the array.

we are now extremely powerful!!