Hash maps

Look out for

Long, repetitive conditionals checking over the same value.

Resolve by

Using a hash map. Set data in an list-like object and access values with variables.

var stateName;
  if ( value == 'DE' ) {
    stateName = 'Delaware';
  } else if ( value == 'MA' ) {
    stateName = 'Massachusetts';
  } else if ( value == 'MD' ) {
    stateName = 'Maryland';
  } else if ( value == 'NJ' ) {
    stateName = 'New Jersey';
  }
});

Edit this demo on CodePen

var stateNames = {
  DE: 'Delaware',
  MA: 'Massachusetts',
  MD: 'Maryland',
  NJ: 'New Jersey',
};

var stateName = stateNames[ value ];

Edit this demo on CodePen

Demo

Edit demo State select - hash map on CodePen

Lesson

Programming is largely about abstractions. Long strings of text and big concepts can be reduced to wee variables, which are easier to both read and manipulate in the code. But ultimately, the goal of programming is work with humans, who live outside the code. They prefer the original, fully-expanded strings and concepts.

The example above deals with this dilemma. We have a <select> menu for some U.S. states. The menu uses the states abbreviations. When a state is selected, its corresponding full state name is displayed in a human-readable sentence.

The initial example gets the state name via a chain of conditionals. It checks the value of a value variable, which requires a separate conditional and assignment for each abbreviation.

if ( value == 'DE' ) {
  stateName = 'Delaware';
} else if ( value == 'MA' ) {
  stateName = 'Massachusetts';
} else if ( value == 'MD' ) {
  stateName = 'Maryland';
} else if ( value == 'NJ' ) {
  stateName = 'New Jersey';
}

This code, of course, functionally gets the job done. But its repetitive nature is irksome. The code blocks all share the exact same structure. The only change are the values being checked and used.

This is an ideal case for a hash map.

A hash map is a fancy programmer word for an un-ordered look-up list. Think of an index in a book. Look up turtles: turn to page 67. Look up tadpole turn to page 42. For each look-up key, it has a looked-up value.

In JavaScript, we can write hash maps with Objects.

var stateNames = {
  DE: 'Delaware',
  MA: 'Massachusetts',
  MD: 'Maryland',
  NJ: 'New Jersey',
};

This object, stored as a variable stateNames, is a list of the states. The object consist of multiple properties, the states. Each property has a key, the state abbreviation, and a value, the state name. On its own, it's just data. What makes it useful is that we access the state names programmatically.

To access a property value, you may typically dot notation

stateNames.DE;
// => 'Delaware'

But, in our example, we don't want to explicitly write out the key (the state's abbreviation in this case). We want to get the property that matches another variable. To do so, we use bracket notation.

stateNames['DE'];
// => 'Delaware'

The brackets allow us to pull the key's value out and use it as a variable.

// use variable in brackets
var abbrev = 'DE';
stateNames[ abbrev ];
// => 'Delaware'

Let's put this this concept into the revised code:

var stateNames = {
  DE: 'Delaware',
  MA: 'Massachusetts',
  MD: 'Maryland',
  NJ: 'New Jersey',
};

var $stateSelect = $('.state-select').on( 'change', function() {
  var value = $stateSelect.val();
  // get state name from hash
  var stateName = stateNames[ value ];
  // ...
});

All the logic with checking the variable is exchanged for a look-up. If the variable matches a key, its property value is returned.

Truthy hash maps

Let's expand on the above example. We'll add a title to the state name, either State or Commonwealth.

var isCommonwealth = value == 'MA' ||
  value == 'VA' || value == 'PA';
var commonwealths = {
  MA: true,
  VA: true,
  PA: true,
};

var isCommonwealth = commonwealths[ value ];

In the initial example, we check if the state is a commonwealth with conditionals for each potential value. This requires multiple conditionals, grouped together with OR || operator.

var isCommonwealth = value == 'MA' || value == 'VA' || value == 'PA';

We can replace this series of conditionals with another hash map.

var commonwealths = {
  MA: true,
  VA: true,
  PA: true,
};

var isCommonwealth = commonwealths[ value ];

Whereas in the previous example we used the value of the matched property, here we are checking if the property is in the map & truthy. If there is no match for the variable, like for commonwealths['NJ'], then its returned value is a falsey undefined.

This pattern is more abstract than a straight set of conditionals. But the benefit is greater readability. Parsing complex conditionals is difficult. Using a hash map reduces the complexity by asking Is this value in the list?

Functions in hash maps

Let's switch things up and look at different demo.

var resultNumber;
if ( operator == 'add' ) {
  resultNumber = a + b;
} else if ( operator == 'subtract' ) {
  resultNumber = a - b;
} else if ( operator == 'multiply' ) {
  resultNumber = a * b;
} else if ( operator == 'divide' ) {
  resultNumber = a / b;
}
var operations = {
  add: function( a, b ) {
    return a + b;
  },
  subtract: function( a, b ) {
    return a - b;
  },
  multiply: function( a, b ) {
    return a * b;
  },
  divide: function( a, b ) {
    return a / b;
  },
};

var resultNumber = operation( a, b );

See the Pen Calculator by David DeSandro (@desandro) on CodePen.

This example is a simple calculator comprised of two input fields and an operator selector. Selecting an operator changes the calculation of the two numbers.

The initial code uses a chain of conditionals to check the operator. The revised code uses a hash map. Instead of string or boolean values, this hash map has functions. Since JavaScript is an object-oriented language, you can use functions as values.

// get the function to be used in the operation
var operation = operations[ operator ];
// call that function
var resultNumber = operation( a, b );