Kodeclik Logo

Our Programs

Courses

Learn More

Schedule

Kodeclik Blog

How to create lists of lists in Javascript

To understand how to work with lists of lists in Javascript, first we should note that Javascript does not have a specific "list" data structure like some other programming languages. However, Javascript uses arrays to implement list-like functionality. Arrays in Javascript are quite versatile and can be used to store and manipulate collections of data in a way similar to lists in other languages.

So a “list of list” is really a nested array in Javascript. Let us see how to create nested arrays in Javascript!

You can create nested arrays in JavaScript using array literals or the Array constructor. Let us checkout both methods next.

Method 1: Creating nested arrays with array literals

If you use array literals, your code will look like:

// Using array literals
const nestedArray = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

Then you can access elements like:

List of lists in Javascript
const value = nestedArray[0][1]; // Accesses the second element of the first inner array
console.log(value); // Output: 2

Note that arrays are zero-indexed: The first element is at index 0, the second at index 1, and so on.

Method 2: Creating nested arrays with array constructors

Alternatively, you can use the Array constructor:

// Using the Array constructor
const anotherNestedArray = new Array(
  new Array(1, 2, 3),
  new Array(4, 5, 6),
  new Array(7, 8, 9)
);

The same code for accessing elements like the above will work.

In the below code examples, we will use the first method but the same concepts will work when you create nested arrays with array constructors.

First, let us discuss when you would need arrays of arrays. Here are five situations where you might need to use arrays of arrays.

Representing Grids or Matrices using arrays of arrays

Arrays of arrays are ideal for representing game boards, pixel matrices, or any 2D grid-like data, for instance:

const chessboard = [
  ['R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R'],
  ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'],
  [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
  [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
  [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
  [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
  ['p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'],
  ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r']
];

Storing tabular data using arrays of arrays

An array of array format is useful for representing data that would typically be stored in a table, such as spreadsheet data or database records:

const studentGrades = [
  ['John', 'Math', 85],
  ['John', 'Science', 78],
  ['Jane', 'Math', 92],
  ['Jane', 'Science', 88]
];

Creating hierarchical data structures

The array of arrays data structure can represent hierarchical relationships, like organizational charts or file systems:

const companyStructure = [
  ['CEO', 
    ['CTO', 
      ['Lead Developer', 
        ['Frontend Dev', 'Backend Dev']
      ],
      ['QA Manager', 
        ['Tester 1', 'Tester 2']
      ]
    ],
    ['CFO', 
      ['Accountant', 'Financial Analyst']
    ]
  ]
];

Grouping related data

Consider:

const weeklyTemperatures = [
  ['Monday', 22, 28, 25],
  ['Tuesday', 21, 29, 24],
  ['Wednesday', 23, 30, 26],
  ['Thursday', 20, 27, 23],
  ['Friday', 22, 28, 25]
];

Here, each inner array represents a day with its minimum, maximum, and average temperatures.

Representing graphs using arrays of arrays

This structure can also represent graphs, where each inner array represents the connections of a node to other nodes.

const adjacencyMatrix = [
  [0, 1, 0, 1],
  [1, 0, 1, 1],
  [0, 1, 0, 0],
  [1, 1, 0, 0]
];

Thus, arrays of arrays can be very natural for many applications and are often the right choice for working with data. Now let us look at some properties of Javascript arrays of arrays.

Javascript arrays of arrays are dynamic

Javascript arrays of arrays can grow or shrink dynamically. For example, consider the below code which starts with a 2x2 matrix; then we add a new row [5, 6]; then expand the first row by adding 7, and finally we remove the last row.

const matrix = [[1, 2], [3, 4]];
console.log("Initial matrix:", matrix);

matrix.push([5, 6]);
console.log("After pushing [5, 6]:", matrix);

matrix[0].push(7);
console.log("After pushing 7 to first row:", matrix);

matrix.pop();
console.log("After popping last row:", matrix);

The output will be:

"Initial matrix:", [[1, 2], [3, 4]]

"After pushing [5, 6]:", [[1, 2], [3, 4], [5, 6]]

"After pushing 7 to first row:", [[1, 2, 7], [3, 4], [5, 6]]

"After popping last row:", [[1, 2, 7], [3, 4]]

Thus, every level of the array of arrays can be modified dynamically, allowing for flexible manipulation of multi-dimensional data structures.

Javascript arrays of arrays can contain mixed data types

In other words, you can store different types of elements (numbers, strings, objects, etc.) in the same array.

const mixedMatrix = [
  [1, "two", { id: 3 }],
  [true, [4, 5], null],
  [function() { return "six"; }, new Date(), Symbol("seven")]
];

console.log("Mixed data type matrix:");
console.log(mixedMatrix);

console.log("\nAccessing and demonstrating different types:");
console.log("Number:", mixedMatrix[0][0]);
console.log("String:", mixedMatrix[0][1]);
console.log("Object:", mixedMatrix[0][2]);
console.log("Boolean:", mixedMatrix[1][0]);
console.log("Nested array:", mixedMatrix[1][1]);
console.log("Null:", mixedMatrix[1][2]);
console.log("Function result:", mixedMatrix[2][0]());
console.log("Date:", mixedMatrix[2][1]);
console.log("Symbol:", mixedMatrix[2][2]);

console.log("\nAdding a new mixed type row:");
mixedMatrix.push([BigInt(8), new Map(), new Set([9, 10])]);
console.log(mixedMatrix);

The output will be:

"Mixed data type matrix:"
[[1, "two", {
  id: 3
}], [true, [4, 5], null], [function() { return "six"; }, [object Date] { ... }, [object Symbol] { ... }]]
"

Accessing and demonstrating different types:"
"Number:", 1
"String:", "two"
"Object:", {
  id: 3
}
"Boolean:", true
"Nested array:", [4, 5]
"Null:", null
"Function result:", "six"
"Date:", [object Date] { ... }
"Symbol:", [object Symbol] { ... }
"

Adding a new mixed type row:"
[[1, "two", {
  id: 3
}], [true, [4, 5], null], [function() { return "six"; }, [object Date] { ... }, [object Symbol] { ... }], [[object BigInt] { ... }, [object Map] { ... }, [object Set] { ... }]]

This example demonstrates a matrix (array of arrays) that contains various data types. The first inner array contains a number, a string, and an object. The second inner array has a boolean, another array (nested), and null. The third inner array includes a function, a Date object, and a Symbol.

We then access and log different elements to show how these varied data types can be used. Finally, we add a new row to the matrix that includes a BigInt, a Map, and a Set, further illustrating the flexibility of JavaScript arrays.

This capability allows for creating complex, heterogeneous data structures within a single nested array. It's particularly useful when dealing with data that doesn't conform to a rigid structure or when you need to represent diverse information in a single data structure.

Remember that while this flexibility is powerful, it's often good practice to maintain consistent data types within arrays for clarity and ease of manipulation, unless your specific use case requires this level of type mixing.

Javascript’s built-in methods for working with array of arrays

Javascript provides various built-in methods for manipulating arrays of arrays. Consider:

// Initialize a matrix (array of arrays)
let matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

console.log("Initial matrix:");
console.log(matrix);

// push(): Add a new row to the end
matrix.push([10, 11, 12]);
console.log("\nAfter push():");
console.log(matrix);

// pop(): Remove the last row
let removedRow = matrix.pop();
console.log("\nAfter pop():");
console.log(matrix);
console.log("Removed row:", removedRow);

// unshift(): Add a new row to the beginning
matrix.unshift([0, 0, 0]);
console.log("\nAfter unshift():");
console.log(matrix);

// shift(): Remove the first row
removedRow = matrix.shift();
console.log("\nAfter shift():");
console.log(matrix);
console.log("Removed row:", removedRow);

// splice(): Remove and/or add rows at a specific index
matrix.splice(1, 1, [13, 14, 15], [16, 17, 18]);
console.log("\nAfter splice():");
console.log(matrix);

// Manipulating inner arrays
matrix[0].push(4);  // Add element to the end of first row
matrix[1].unshift(12);  // Add element to the beginning of second row
matrix[2].splice(1, 1, 20);  // Replace second element of third row

console.log("\nAfter manipulating inner arrays:");
console.log(matrix);

// map(): Transform the matrix
let squaredMatrix = matrix.map(row => row.map(num => num * num));
console.log("\nSquared matrix using map():");
console.log(squaredMatrix);

// filter(): Keep only rows where all elements are even
let evenRowsMatrix = matrix.filter(row => row.every(num => num % 2 === 0));
console.log("\nMatrix with only even rows using filter():");
console.log(evenRowsMatrix);

// flat(): Flatten the matrix into a single array
let flattenedMatrix = matrix.flat();
console.log("\nFlattened matrix using flat():");
console.log(flattenedMatrix);

The output will be:


"Initial matrix:"
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
"

After push():"
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
"

After pop():"
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
"Removed row:", [10, 11, 12]
"

After unshift():"
[[0, 0, 0], [1, 2, 3], [4, 5, 6], [7, 8, 9]]
"

After shift():"
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
"Removed row:", [0, 0, 0]
"

After splice():"
[[1, 2, 3], [13, 14, 15], [16, 17, 18], [7, 8, 9]]
"

After manipulating inner arrays:"
[[1, 2, 3, 4], [12, 13, 14, 15], [16, 20, 18], [7, 8, 9]]
"

Squared matrix using map():"
[[1, 4, 9, 16], [144, 169, 196, 225], [256, 400, 324], [49, 64, 81]]
"

Matrix with only even rows using filter():"
[[16, 20, 18]]
"

Flattened matrix using flat():"
[1, 2, 3, 4, 12, 13, 14, 15, 16, 20, 18, 7, 8, 9]

The code example above demonstrates the following array methods:

push(): Adds a new row to the end of the matrix.

pop(): Removes and returns the last row of the matrix.

unshift(): Adds a new row to the beginning of the matrix.

shift(): Removes and returns the first row of the matrix.

splice(): Removes existing rows and/or adds new rows at a specific index.

Inner array manipulation: Demonstrates push(), unshift(), and splice() on individual rows.

map(): Creates a new matrix by applying a function to each element.

filter(): Creates a new matrix containing only the rows that pass a test.

flat(): Flattens the nested array structure into a single-dimensional array.

These methods provide powerful tools for manipulating arrays of arrays, allowing you to add, remove, replace, transform, and restructure data in various ways. Each method serves a specific purpose and can be combined to perform complex operations on multi-dimensional array structures.

Converting a list to a list of lists in Javascript

Sometimes you would like to create a list of lists from a flattened list in Javascript. To transform your list into a list of lists where each sublist contains the same items grouped together, you can use the reduce() method in JavaScript. Here's how you can achieve this:

const a = [1, 1, 1, 2, 3, 3];

const groupedList = a.reduce((acc, curr) => {
  const existingGroup = acc.find(group => group[0] === curr);
  if (existingGroup) {
    existingGroup.push(curr);
  } else {
    acc.push([curr]);
  }
  return acc;
}, []);

console.log(groupedList);

The program uses the reduce() method to iterate over each element in the input array a. For each element, it checks if there's already a group (subarray) in the accumulator that starts with the same value as the current element. This check is done using the find() method on the accumulator. If such a group exists, the current element is pushed into that group. If no matching group is found, a new group is created with the current element as its only member, and this new group is pushed into the accumulator.

The reduce() method starts with an empty array as the initial value of the accumulator. As it processes each element, it builds up the grouped structure, resulting in a new array where each subarray contains elements that were adjacent and identical in the original array. This approach effectively transforms the flat input array into a list of lists, grouping consecutive identical elements together.

The output is:

[[1, 1, 1], [2], [3, 3]]

In summary, an array of arrays provides a structured way to organize and access related data. They allow for efficient representation of complex data structures and relationships, making it easier to manipulate and process information in your Javascript code!

Want to learn Javascript with us? Sign up for 1:1 or small group classes.

Kodeclik sidebar newsletter

Join our mailing list

Subscribe to get updates about our classes, camps, coupons, and more.

About

Kodeclik is an online coding academy for kids and teens to learn real world programming. Kids are introduced to coding in a fun and exciting way and are challeged to higher levels with engaging, high quality content.

Copyright @ Kodeclik 2024. All rights reserved.