Codesmith Blog

Your Blog Post CSX Challenge Solution: arrayBuilder - a Step-by-Step Approach to Solving the Challenge

Written by Ruth Anam | Dec 3, 2019 4:53:00 PM

In this blog post, we will go over an approach to a problem from Codesmith’s CSX Functions and Execution Context unit. This unit is focused on building a solid JavaScript foundation for code execution, memory (variable environment), execution context, and the call stack. The problem we’ll go over today, arrayBuilder, is this unit’s last challenge and an important one to discuss because it covers multiple topics covered within the unit on the CSX platform while also building on the difficulty compared to the challenges before it.

Let’s take a look at the prompt for this problem:

// Write a function, arrayBuilder, that 

// takes in a count object and returns an array 

// filled with the appropriate numbers of elements. 

// The order of the elements in the array does 

// not matter, but repeated elements should be grouped.

Now let’s break down this prompt. If you’d like, feel free to also watch the accompanying video solution for the problem, here.

STEP 0

Pseudocoding, or representing the implementation of your approach to solving a problem in the form of adding comments to your code editor before actually coding out anything, is as important as it is beneficial. If you ever get stuck while coding, you can look back at your pseudocode to remind yourself of what you wanted to do initially. Usually, that’s enough to get unstuck.

After reading the prompt, what do we know? We know that we’re being provided an object as our input because the prompt mentions that our function should take in a count object. We are also told to return an array as our output. Our pseudocode will indicate that our input is an object and our output should be an array.

function arrayBuilder(obj) {

  // Input is an object

  // Output to return is an array

};

The boiler plate for this challenge provided us with console.log statements, which show some test cases our code has to pass:

console.log(arrayBuilder( {'cats': 2, 'dogs': 1} )); 

// => ['cats', 'cats', 'dogs']

console.log(arrayBuilder( {} )); 

// => []

We see that an object is being passed into a function call. This object contains two property-value (key-value) pairs: ‘cats’: 2 and ‘dogs’: 1. The expected result of this function invocation indicates that our output array should contain the property, ‘cats’, as an element occurring twice, and the property, ‘dogs’, as an element occurring once.

We’ll walk through one solution to this challenge step-by-step.

STEP 1

We know that we have to output an array of some sort (remember that the prompt asked us to return an array). Our first bit of code will be to use const to declare a variable, outputArray, and initialize it to an empty array. Why did I use const to declare the variable? We don’t plan on reassigning this array. Arrays are mutable, whereas primitive values are immutable. This means that we can modify an element at a specific index, apply array methods to the array, and many other things that mutate the array without having to worry about reassigning it. Don’t forget to use a semicolon to indicate the end of an expression! This is a great way to make sure your code is readable, not only for yourself but for anyone else who will be looking at your code.

function arrayBuilder(obj) {

  // Input is an object

  // Output to return is an array

 

  const outputArray = [];

}

STEP 2

Let’s now think about what we want to do with this array. We expect to insert properties as elements into this array a certain number of times based on a property’s corresponding value. This means we will have to use the array method, push(), at some point.

However, for now, let’s consider how we can iterate through the properties of an object. How does one do this? With a for...in loop. One can use a for...in loop to iterate through the properties of an object. For more in formation about for...in loops check out the documentation for it on MDN! We can gain direct access to the properties inside of an object using this kind of loop! Let’s take a look at how we might do that:

function arrayBuilder(obj) {

  // Input is an object

  // Output to return is an array

 

  const outputArray = [];

 

  for (let key in obj) {

    

  }

}

The expression inside the parentheses is instructing JavaScript to declare a variable that will be reassigned (hence, the use of the let keyword) each time we iterate through a different property within the object, obj. That means we can access the corresponding value for a specific key (another word for a property) inside of this object. What are these values? They’re essentially numbers indicating the number of times a key should appear in outputArray. Let’s store this value inside of a count variable, repeatCount. How does one access the value of a property inside of an object? Bracket notation!

function arrayBuilder(obj) {

  // Input is an object

  // Output to return is an array

 

  const outputArray = [];

 

  for (let key in obj) {

    let repeatCount = obj[key];

  }

}

TIP: Use bracket notation when working with variables. With bracket notation, properties are accessed using an expression that gets resolved into a string. Variables represent these expressions and become resolved to a string when accessing an object property. In comparison, dot notation only checks for a matching identifying property name rather than evaluating an expression, which does not require strings to do so.

STEP 3

We want to decrement repeatCount. Why would we want to decrement this variable? Could we push the property into outputArray, decrement repeatCount by 1, push the property into outputArray again, and decrement repeatCount again until this variable reaches 0? You bet we can! Just note that we don’t want to push the property when our repeatCount reaches 0. Try to think about why this would be the case.

Let’s say we want to push a property two times. If our variable starts at 2, we can push once, decrement the variable to 1, push a second time, and then decrement the variable to 0. We don’t want to push a third time. We don’t want to do anything after repeatCount decrements down to 0. With this in mind, we can use a while loop, because we are repeating a set of actions multiple times with the condition of repeatCount having to be greater than 0:

function arrayBuilder(obj) {

  // Input is an object

  // Output to return is an array

 

  const outputArray = [];

 

  for (let key in obj) {

    let repeatCount = obj[key];

    while (repeatCount > 0) {

      

    }

  }

}

Let’s also go ahead and push the current key we are iterating on into outputArray and then decrement outputArray by 1 while remembering to insert semicolons as necessary for better code readability.

function arrayBuilder(obj) {

  // Input is an object

  // Output to return is an array

 

  const outputArray = [];

 

  for (let key in obj) {

    let repeatCount = obj[key];

 

    while (repeatCount > 0) {

      outputArray.push(key);

      repeatCount -= 1;

    }

  }

}

STEP 4

Up until now, we’ve written several lines of code. However, this code will not be useful unless we actually return data to the function caller whenever arrayBuilder is invoked.

Why do we have to return something? We use return statements to pass back data we need from a function. The return statement acts as a command that stops the execution of a function and when specified with a value, return sends that value to the function caller. This value is not stored anywhere and to store this value, you would have to set the variable to equal the function invocation.

If there is no return statement, the function returns the value undefined to the function caller.

All of that is to say the following: We need to return our output array!

function arrayBuilder(obj) {

  // Input is an object

  // Output to return is an array

 

  const outputArray = [];

 

  for (let key in obj) {

    let repeatCount = obj[key];

 

    while (repeatCount > 0) {

      outputArray.push(key);

      repeatCount -= 1;

    }

  }

  return outputArray;

}

Let’s run our code to test whether our output matches what we expect the console.log statements to output.

Let’s also make sure we pass the checks, which are essentially tests written to make sure that our code is actually doing what the problem actually expects the code to do:

That’s our working solution for this problem, great job coming this far! Hopefully, you’ve learned a thing or two. Note that this is just one approach and that there might be other solutions, all with their own pros and cons. Thanks for following along!