Skip to content

Latest commit

 

History

History
792 lines (622 loc) · 25 KB

File metadata and controls

792 lines (622 loc) · 25 KB

8. Arrays Keep Things in Order

[toc]


8.1. Arrays Are Like Strings

Arrays are similar to strings, but are more general collection types. Like strings, arrays are a sequence of values that can be access via an ordered index. Unlike strings, arrays can store data of any type including other arrays.

The figure below demonstrates an array of named languages. The array contains four strings, each of those values has an index position. $$ \begin{aligned} \text{languages} & \rightarrow & \begin{array}{|c|c|} \hline 0 & \text{"Python"} \ \hline 1 & \text{"C#"} \ \hline 2 & \text{"Java"} \ \hline 3 & \text{"JavaScript"} \ \hline \end{array} \end{aligned} $$

8.1.1. Declaring an Array

Programmers have multiple ways to declare a new array. Array literal notation ([]) is the most simple. Anything enclosed in the square brackests will be items in the array. Each item should be separated by a comma (,). If there are no items inside the brackets, then the array is considered empty.

let emptyArray = [];

let languages = ["Python","C#","Java","JavaScript"];

Arrays can also be declared on multiple lines.

let languages = [
    "Python",
    "C#",
    "Java",
    "JavaScript"
];

8.1.2. Array Length

To find the length of an aray, use the length property, just like with strings. JavaScript arry length is NOT fixed, meaning you can add or remove items dynamically.

let emptyArray = [];
console.log(emptyArray.length);		// 0

let languages = ["Python","C#","Java","JavaScript"];
console.log(languages.length);		// 4

ℹ️ NOTE: In other languages, such as Java or C#, arrays are of static length requiring the length of an array to be declared upon creation. In JavaScript this is optional. Each cell will be filled with an undefined value until one is chosen.

var four = new Array(4);	// [undefined, undefined, undefined, undefined];
four.fill(0);				// [0,0,0,0]
four.fill("Bob");			// ["Bob","Bob","Bob","Bob"]

8.1.3. Varying Data Types

JavaScript arrays can hod a mixture of values of any type.

let grabBag = ["A String",true, 99, 105.7];

ℹ️ NOTE: It's rare that you would store data of multiple tyes in the same array, beacause grouped data is usually the same data type. In other languages, like Java or C#, all items in the array have to be of the same type.

8.1.4. Check Your Understanding ✅

Question: What is the lenght of the two arrays? (Hint: look closely at the quotes in the classes array).

let classes = ["science, computer, art"];

let teachers = ["Jones", "Willoughby", "Rhodes"];

How can you change the classes array declaration to have the same number of items as the teachers array?

Answer:

  1. One and three. The first one is not separated each comma.
  2. Insert quotes at the commas.

🤪 Their answer: "Yes, I have though of an answer, and I would like to check my thinking after I submit this quiz."

8.2. Working With Arrays

8.2.1. Bracket Notation and Index

As previously discussed, arrays are an orderd collection where each item can be access via index. Similar to strings, an index in an array is the number order given to items. Individual items can be accessed using bracket notation. (array[index]). Indexes are zero-based going from 0 to array.length-1.

let languages = [
    "Python",		// index 0
    "C#",			// index 1
    "Java",			// index 2
    "JavaScript"	// index 3
];
console.log(languages[0]);	// Python
console.log(languages[3]);	// JavaScript

// What will happen when index 4 is requested?
console.log(languages[4]);	// undefined

Notice that undefined was printed out when index 4 was referenced. undefined is returned when you request an index that the array does not contain.

ℹ️ NOTE: undefined is a special value in JavaScript that means no value has been assigned. We will discuss undefined in this class more later.

Example: undefined will be returned for any index that is outside of the array's index range.

let languages = ["Python","C#","Java","JavaScript"];
console.log(languges[-1]);	// undefined
console.log(languges[100]);	// undefined

8.2.2. Arrays are Mutable

In programming, mutability refers to what happens when you attempt to change a value. Remember that ==strings are immutable==, meaning that any changes ot a string results in a new string being created. In contrast, ==arrays are mutable==, meaning that individual items in an array can be edited without a new array being created.

Example: Update an item in an array using bracket notation and index.

let frameworks = ["React", "Angular", "Ember"];
console.log(frameworks);

// Set value of index 2 to be "Vue"
frameworks[2] = "Vue";

// Notice the value at index 2 is now "Vue"
console.log(frameworks);
[ 'React', 'Angular', 'Ember' ]
[ 'React', 'Angular', 'Vue' ]

8.3. Array Methods

As with strings, JavaScript provides us with useful methods for arrays. These methods will either alter an existing array, return information about the array, or create and return a new array.

8.3.1. Common Array Methods

ℹ️ NOTE: Much like I said in the previous chapter (namely in section 7.5.1) I'm not going to recreate the table here. There are way more methods than the table in the textbook has listed here. I will list the string methods in another document in my notes repository. In the mean time, take a look at

🤓 Actually... Also, they got their table wrong. .split is not part of the Array class. It's part of the String class and it suppost to be the complement of Array's .join method.

8.3.2. Check Your Understanding ✅

Use the information from the Array and String documentation to answer the following questions.

Question: What is printed by the following code?

let charles = ['coder', 'Tech', 47, 23, 350];
charles.sort();
console.log(charles);

a. [350, 23, 47, 'Tech', 'coder'] b. ['coder', 'Tech', 23, 47, 350] c. [23, 47, 350, 'coder', 'Tech'] d. [23, 350, 47, 'Tech', 'coder']

Answer: d. (Don't forget, .sort() is case-sensitive!)

Question: Which statement converts the string str = 'LaunchCode students rock!' into the array ['LaunchCode', 'students', 'rock!']? a. str.join(" "); b. str.split(" "); c. str.join(""); d. str.split("");

Answer: b.

Question: What is printed by the following program?

let groceryBag = ['bananas', 'apples', 'edamame', 'chips', 'cucumbers', 'milk', 'cheese'];
let selectedItems = [];

selectedItems = groceryBag.slice(2, 5).sort();
console.log(selectedItems);

a. ['chips', 'cucumbers', 'edamame'] b. ['chips', 'cucumbers', 'edamame', 'milk'] c. ['cheese', 'chips', 'cucumbers'] d. ['cheese', 'chips', 'cucumbers', 'edamame']

Answer: a.

8.4. Multi-Dimensional Arrays

Earlier we learned that arrays can store any type of value. If that is true, can we store arrays inside of array? Yes!

A multi-dimensional array is an array of arrays, meaning that the values inside the array are also arrays. The inner arrays can store other values such as strings, numbers, or even other arrays.

This figure illustrates how it would look like. $$ \begin{aligned} \text{synonyms} & \rightarrow & \begin{array}{|c|c|c|c|} \hline & 0 & 1 & 2 \ \hline 0 & \text{"table"} & \text{"grid"} & \text{"spreadsheet"}\ \hline 1 & \text{"determined"} & \text{"serious"} & \text{"strong"} \ \hline 2 & \text{"potential"} & \text{"possible"} & \text{"likely"} \ \hline 3 & \text{"enhance"} & \text{"improve"} & \text{"upgrade"} \ \hline \end{array} \end{aligned} $$

8.4.1. Two Dimension Arrays

The simplest form of a multi-dimensional array is a two dimensional array, or "matrix". A matrix is like a spreadsheet with rows and columns. To access items in a matrix, use square bracket notation and two indexes array[row][column]. The first index is for the outer array, or the "row". The second index is for the inner array, or "column".

ℹ️ NOTE: The row and column analogy is used to help visualize a two dimensional array, however it's not a perfect analogy. There are no specific JavaScript language rules forcing the inner arrays to all have the same length. The inner arrays are separate arrays that can be of different length.

Example: Use a two dimensional array to contain three different lists of space shuttle crews.

let shuttleCrews = [
   ['Robert Gibson', 'Mark Lee', 'Mae Jemison'],
   ['Kent Rominger', 'Ellen Ochoa', 'Bernard Harris'],
   ['Eilen Collins', 'Winston Scott',  'Catherin Coleman']
];

console.log(shuttleCrews[0][2]);	// Mae Jemison
console.log(shuttleCrews[1][1]);	// Ellen Ochoa
console.log(shuttleCrews[2][1]);	// Winston Scott

8.4.2. Multi-Dimensions and Array Methods

In a matrix, both inner and outer arrays can be altered with array methods. However, bracket notation must be used correctly.

To apply a method to the outer array, the syntax is:

matrix.method();

To apply a method to one of the inner arrays, the syntax is:

matrix[row].method();

Example: Use array methods to add an addition crew array and alter existing arrays.

let shuttleCrews = [
   ['Robert Gibson', 'Mark Lee', 'Mae Jemison'],
   ['Kent Rominger', 'Ellen Ochoa', 'Bernard Harris'],
   ['Eilen Collins', 'Winston Scott',  'Catherin Coleman']
];

let newCrew = ['Mark Polansky', 'Robert Curbeam', 'Joan Higginbotham'];

// Add a new crew array to the end of shuttleCrews
shuttleCrews.push(newCrew);
console.log(shuttleCrews[3][2]);

// Reverse the order of the crew at index 1
shuttleCrews[1].reverse();
console.log(shuttleCrews[1]);
Joan Higginbotham
[ 'Bernard Harris', 'Ellen Ochoa', 'Kent Rominger' ]

8.4.3. Beyond Two Dimensional Arrays

Generally, there is no limit to how many dimensions you can have when creating arrays. However, it is rare that you will use more than two dimensions. Later on in this class, we will leanr about more collection types that can handle complex problems beyond the scope of two dimensional arrays.

8.4.4. Check Your Understanding ✅

Question: What are the two dimensional indexes for "Jones"?

let school = [
["science", "computer", "art"],
["Jones", "Willoughby", "Rhodes"]
];

How would you add "dance" to the end of the first array in school[0]?

How would you add "Holmes" to the start of the second array in school[1]?

Answer:

A. school[1][0] (Yes, this is the correct answer! I was right!)

B. school[0].push("dance");

C. school[1].unshift("Holmes");

ℹ️ NOTE: I updated the questions on parts B and C since the questions were different.

8.5. Exercises: Arrays 🏃

CENSORED

8.6. Studio: Strings and Arrays 🎙️

CENSORED

8.6.1. Before You Start

8.6.2. String Modification

8.6.3. Array and String Conversion

8.6.4. Bonus Mission: Multi-dimensional Arrays 🚀


🧪 Expand your knowledge: Array and String Methods

Given the following array with a length of 4, here's how we would use .push, .pop, .unshift, and .shift: $$ \begin{aligned} \begin{array}{|c|c|c|} \hline 0 & 1 & 2 & 3 \ \hline \text{"orange"} & \text{"yellow"} & \text{"green"} & \text{"blue"} \ \hline \end{array} \end{aligned} $$ A lot of books like to demonstrate these functions using the "plate stack" method. But Arrays in JavaScript are more like "queues" (Pronounced "Kewz") which are pretty much lines, like the one you would be in at the checkout at the supermarket.

let colors = ["orange","yellow","green","blue"];
console.log(colors); 		    // [ 'orange', 'yellow', 'green', 'blue' ]
console.log(colors.length);		// 4

Push

Push is pretty much like the person who just joined at the end of the line.

Push takes in the new item and puts it at the end. $$ \begin{aligned} \text{Before: } & & & \begin{array}{|c|c|c|} \hline 0 & 1 & 2 & 3 \ \hline \text{"orange"} & \text{"yellow"} & \text{"green"} & \text{"blue"} \ \hline \end{array} \leftarrow \boxed{\text{"violet"}} \ \text{After: } & & & \begin{array}{|c|c|c|} \hline 0 & 1 & 2 & 3 & 4 \ \hline \text{"orange"} & \text{"yellow"} & \text{"green"} & \text{"blue"} & \text{"violet"} \ \hline \end{array} \end{aligned} $$ Push will return the new length of the array.

console.log(colors); 			   // [ 'orange', 'yellow', 'green', 'blue' ]
console.log(colors.length);			// 4
console.log(colors.push("violet"));	// 5
console.log(colors); 			  // [ 'orange', 'yellow', 'green', 'blue', 'violet' ]
console.log(colors.length);		    // 5

Pop

Pop can be though of as that one person who gets out of line at the end because they forgot something. $$ \begin{aligned} \text{Before: } & & & \begin{array}{|c|c|c|} \hline 0 & 1 & 2 & 3 & 4 \ \hline \text{"orange"} & \text{"yellow"} & \text{"green"} & \text{"blue"} & \text{"violet"} \ \hline \end{array} \ \text{After: } & & & \begin{array}{|c|c|c|} \hline 0 & 1 & 2 & 3 \ \hline \text{"orange"} & \text{"yellow"} & \text{"green"} & \text{"blue"} \ \hline \end{array} \rightarrow \boxed{\text{"violet"}} \end{aligned} $$

console.log(colors); 			// [ 'orange', 'yellow', 'green', 'blue', 'violet' ]
console.log(colors.length);		 // 5
console.log(colors.pop());		 // 'violet'
console.log(colors); 		     // [ 'orange', 'yellow', 'green', 'blue' ]
console.log(colors.length);		 // 4

Unshift

Unshift is like push, but it happens at the beginning of the queue. That person is the guy who butts in front of everybody else in the line.

Notice that the indices have all changed value! $$ \begin{aligned} \text{Before: } & & \boxed{\text{"red"}} \rightarrow \begin{array}{|c|c|c|} \hline 0 & 1 & 2 & 3 \ \hline \text{"orange"} & \text{"yellow"} & \text{"green"} & \text{"blue"} \ \hline \end{array} \ \text{After: } & & \begin{array}{|c|c|c|} \hline 0 & 1 & 2 & 3 & 4 \ \hline \text{"red"} & \text{"orange"} & \text{"yellow"} & \text{"green"} & \text{"blue"} \ \hline \end{array} \end{aligned} $$

console.log(colors); 			   	// [ 'orange', 'yellow', 'green', 'blue' ]
console.log(colors.length);			// 4
console.log(colors.unshift("red"));	 // 5
console.log(colors); 			   	// [ 'red', 'orange', 'yellow', 'green', 'blue' ]
console.log(colors.length);		    // 5

Shift

Shift is like pop. You entered the line one way, and now you are leaving the other way. $$ \begin{aligned} \text{Before: } & & \begin{array}{|c|c|c|} \hline 0 & 1 & 2 & 3 & 4 \ \hline \text{"red"} & \text{"orange"} & \text{"yellow"} & \text{"green"} & \text{"blue"} \ \hline \end{array} \ \text{After: } & & \boxed{\text{"red"}} \leftarrow \begin{array}{|c|c|c|} \hline 0 & 1 & 2 & 3 \ \hline \text{"orange"} & \text{"yellow"} & \text{"green"} & \text{"blue"} \ \hline \end{array} \end{aligned} $$

console.log(colors); 			// [ 'red', 'orange', 'yellow', 'green', 'blue' ]
console.log(colors.length);		 // 5
console.log(colors.shift());	 // 'red'
console.log(colors); 		     // [ 'orange', 'yellow', 'green', 'blue' ]
console.log(colors.length);		 // 4

What can you do with this?

const input = require('readline-sync');

let arr = [];
let len = 5;

console.log(`Give me ${len} numbers:`);
for(let i = 0; i < len; i++){
    arr.push(Number(input.question(`(${i+1}/${len}): `)));
}

console.log("Great, now I'm just going to dump them out");
for(let i = 0; i < len; i++){	// You will be glad you DIDN'T use arr.length here!
    console.log(arr.shift());
}

There's another computer language called Bash that uses loops (which we will talk about in the next chapter), that reads a line of text, breaks it into an array, then reads each argument using a shift command, removing each argument from the beginning. This is sort of why when we pop an item off from the beginning we say "shift" rather than "unshift".


🎗️ TODO Finish this later. Also include .splice and .slice.

🧪Expand your knowledge: String reverse

A string is pretty much an array of characters. But there's still some folks having some trouble how flexible this exchange between string and array type are. Let's take a string and break it apart. $$ \boxed{\text{"Jason"}} \implies \boxed{\begin{array}{c} 0 & 1 & 2 & 3 & 4 \ \hline \text{"J"} & \text{"a"} & \text{"s"} & \text{"o"} & \text{"n"} \end{array}} $$ Sure, that looks like how I described arrays. The top row indicates the index (position) of the character, and the bottom row is the corresponding character to that index.

A string has separators, if you count nothing as a separator. We'll show this shortly.

.split and .join need an argument inorder to work.

split

We disassemble a String into an Array using .split. $$ \boxed{\begin{array}{c} 0 & 1 & 2 & 3 & 4 \ \hline \text{"J"} & \text{"a"} & \text{"s"} & \text{"o"} & \text{"n"} \end{array}} \xrightarrow{\text{split('')}} \begin{array}{|c|} \hline 0 & 1 & 2 & 3 & 4 \ \hline \text{"J"} & \text{"a"} & \text{"s"} & \text{"o"} & \text{"n"} \ \hline \end{array} $$

let str = "Jason";
console.log(str);			// 'Jason'
let arr = str.split('');	
console.log(arr);			// [ 'J', 'a', 's', 'o', 'n' ]

join

We assemble an Array into a String using join. $$ \begin{array}{|c|} \hline 0 & 1 & 2 & 3 & 4 \ \hline \text{"J"} & \text{"a"} & \text{"s"} & \text{"o"} & \text{"n"} \ \hline \end{array} \xrightarrow{\text{join('')}} \boxed{\begin{array}{c} 0 & 1 & 2 & 3 & 4 \ \hline \text{"J"} & \text{"a"} & \text{"s"} & \text{"o"} & \text{"n"} \end{array}} $$

let arr = ["J","a","s","o","n"];	
console.log(arr);					// [ 'J', 'a', 's', 'o', 'n' ]
let str = arr.join('');
console.log(str);					// 'Jason'

Split and Join Need an Argument

Here's what happen when you don't use an argument in .split or .join

console.log("Jason".split());				// [ 'Jason' ]
console.log(["J","a","s","o","n"].join());	// 'J,a,s,o,n'

🎗️ TODO: Here would be a good place to talk about Regular Expression.

Arrays can reverse, but Strings Cannot

console.log(["J","a","s","o","n"].reverse());	//	[ 'n', 'o', 's', 'a', 'J' ]
console.log("Jason".reverse());	// ❌ TypeError: "Jason".reverse is not a function

But there is a way around this!

console.log("Jason".split('').reverse().join(''));	// 'nosaJ'

Arrays can splice

🎗️ TODO See this.

Array and String both have concat

🎗️ TODO Do this later. See this and this.

str.concat(str2[, ...strN])
arr.concat(arr2[, ...arrN])
arr.concat(val1[, ...valN])

String Concatenation

Array Concatenation

Mixed Concatenation

Array and String both have slice

🎗️ TODO Complete this section. See this and this.

str.slice( beginIndex[, endIndex] )
arr.slice([beginIndex[, endIndex]])

Let's start with how .slice works in strings. Slice can have two arguments.

  • beginIndex - The zero-based index at which to begin extraction.
    • If omited, beginIndex is treated as 0.
    • If positive and less than str.length, and no endIndex is defined, the new string will be from the beginIndex position to the end of the string. Basically it would be like saying str.slice(beginIndex,str.length-1).
    • If positive and greater than or equal to str.length, and noendIndex is defined, the new string is an empty string, ''.
    • If negative and the absolute value of beginIndex is less than str.length, and no endIndex is defined, the beginIndex is str.length - beginIndex. So in a string that has a length of 5, if beginIndex is -1, it will be treated as if we had used 4 as the beginIndex.
  • endIndex - (Optional) The zero-based index before which to end extraction. The characters at this index will not be included.
    • If omitted, endIndex will be treated as str.length-1.

Let's try it with string first.

let str = "Jason";
str.length;		// 5
str.slice();	// 'Jason'
str.slice(0);	// 'Jason'
str.slice(1);	// 'ason'
str.slice(2);	// 'son'
str.slice(3);	// 'on'
str.slice(4);	// 'n'
str.slice(5);	// ''
str.slice(6);	// ''
str.slice(-1);	// 'n'
str.slice(-2);	// 'on'
str.slice(-3);	// 'son'
str.slice(-4);	// 'ason'
str.slice(-5);	// 'Jason'
str.slice(-6);	// 'Jason'

Let's make a table out of this to make it easier to visualize.

// TODO: Do a splice table later!
let str = "Jason";

const FS = '|';   // field (column) separator
const RS = '\n';  // record (row) separator
const PAD = ' ';  // padding character

let tbl = ""; // Start with an empty table
//let row = ""; // with an empty row 

// How row and column headers should look
function tblEdge(width,val){
  return String(val).padStart(width,PAD);
}

// Table Header Row
function tblHeader(width,low,high){
  let row = FS;  // start each row with a pipe
  row += PAD.repeat(width); // top-left corner cell
  row += FS;
  // Numbered row header with index in each cell
  for(let i = low; i < high; i++){
    row += tblEdge(width,i) + FS;
  }
  return row + RS;
}

console.log("rows represent beginIndex");
console.log("cols represent endIndex");
console.log();

//tbl += FS + "none".padStart(str.length,PAD);
tbl = tblHeader(str.length,-str.length-1,str.length+2);

//tbl = tbl.split('|').splice(2,0,"none".padStart(str.length,PAD)).join('|'); // splice is a destructive function! It returns removed elements. We can't do this like we did with reverse!;

// Insert position is 2 because there's a pipe at the beginning
// which makes tbl[0] = '' and tbl[1] = '     '.
tbl = tbl.split('|');
tbl.splice(2,0,"none".padStart(str.length,PAD));
tbl = tbl.join('|');

let out = "";
let row;
for(let i = -str.length -1; i <= str.length+1; i++){
  row = FS + tblEdge(str.length,i) + FS;  // Number our rows

  // This row represent ommiting endIndex
  row += str.slice(i).padStart(str.length,PAD) + FS;
 
  for(let j = -str.length-1; j <= str.length+1; j++){
    row += str.slice(i,j).padStart(str.length,PAD).padEnd(str.length,PAD) + FS;
  }
  tbl += row + RS;
}

console.log(tbl);

image-20200206152919124

String's substring.

🎗️ TODO: What's the difference between slice and substring?

str.substring(beginIndex[,endIndex])

Substring can have two arguments

  • beginIndex - The index of the first character to include in the returned substring.
  • endIndex (optional) - The index of the first character to exclude from the returned substring.

Substring will return a new string containing the specified part of the given string. It will extract chracters from beginIndex up to but not including endIndex.

  • If there are no arguments, substring will return the string unchanged. ("Jason".substring() will return "Jason".) But you probably don't intendt to use it like that.
  • If endIndex is ommitted, substring() extracts characters to the end of the string. In other words, if endIndex is not used, endIndex will be set to the string length.
  • If beginIndex is equal to endIndex, substring returns an empty string. This is pretty obvious from what we saw when we used slice().
  • if beginIndex is greater than endIndex, then the effects of substring() are as if the two arguments were swapped.
  • Any argument that is less than zero or greater than the lenght of the string (str.length), are treated as if they were zero or the length of the string respectively.
  • Any argument that is NaN is treated as if it were 0.

The difference between .slice and .substring are pretty clear. (See this link.)

image-20200207144915248

pad and trim

🎗️ TODO

str = "  Jason  ";
str.trim();
str.trimStart();
str.trimEnd();
str = "Jason";
str.padStart();
str.padEnd();
// but no str.pad();	// 🎗TODO: Can there be?

🏁 Woo! Eight chapters done. Up next: Repeating With Loops


#LaunchCode