Code Review Videos > Map, Filter, Reduce > [Easy] Map in TypeScript

[Easy] Map in TypeScript

The following are the TypeScript solutions to the map problems defined under Map, Filter, Reduce.

As TypeScript / JavaScript are languages I am comfortable with, the only things I will call out are those that I think are of any interest. Always happy to answer questions though. Just leave a comment.

Easy Map

// easy-map.spec.ts

import { mapBool, mapNumbers, mapString } from "./easy-map";

describe("easy map", () => {
  describe("mapNumbers", () => {
    test("zero element array", () => {
      const given: number[] = [];
      expect(mapNumbers(given)).toEqual([]);
    });

    test("one element array", () => {
      const given = [1];
      expect(mapNumbers(given)).toEqual([1]);
    });

    test("multiple element array", () => {
      const given = [3, 5, 10];
      expect(mapNumbers(given)).toEqual([9, 25, 100]);
    });
  });

  describe("mapString", () => {
    test("zero element array", () => {
      const given: string[] = [];
      expect(mapString(given)).toEqual([]);
    });

    test("one element array - empty", () => {
      const given = [""];
      expect(mapString(given)).toEqual([]);
    });

    test("one element array - valid", () => {
      const given = ["a"];
      expect(mapString(given)).toEqual(["A"]);
    });

    test("one element array - messy", () => {
      const given = ["XYZ AbC "];
      expect(mapString(given)).toEqual(["Xyz abc"]);
    });

    test("multiple element array", () => {
      const given = [
        "aaa",
        "bbb",
        "ccc",
        "a",
        "AAA",
        "Abba",
        "",
        "   l33t sp4aK ",
      ];
      expect(mapString(given)).toEqual([
        "Aaa",
        "Bbb",
        "Ccc",
        "A",
        "Aaa",
        "Abba",
        "L33t sp4ak",
      ]);
    });
  });

  describe("mapBool", () => {
    test("zero element array", () => {
      const given: boolean[] = [];
      expect(mapBool(given)).toEqual([]);
    });

    test("one element array - falsy", () => {
      const given = [false];
      expect(mapBool(given)).toEqual(["false"]);
    });

    test("one element array - truthy", () => {
      const given = [true];
      expect(mapBool(given)).toEqual(["true"]);
    });

    test("multiple element array - mixed", () => {
      const given = [false, true, false, true, false, true];
      expect(mapBool(given)).toEqual([
        "false",
        "true",
        "false",
        "true",
        "false",
        "true",
      ]);
    });
  });
});Code language: PHP (php)

And the associated implementation:

// easy-map.ts

export const mapNumbers = (input: number[]): number[] =>
  input.map((number) => number * number);

export const mapString = (input: string[]): string[] =>
  input
    .map((string) => string.trim())
    .filter((string) => string)
    .map(
      (string) =>
        `${string[0].toUpperCase()}${string.substring(1).toLowerCase()}`
    );

export const mapBool = (input: boolean[]): string[] =>
  input.map((bool) => (bool ? "true" : "false"));

export default {
  mapBool,
  mapNumbers,
  mapString,
};Code language: JavaScript (javascript)

Input Does Not Have To Match Output

In the case of the map function we take an array as the input, we run a function against every element in the input array, and then we return an array as the result.

Our map function need not return an array of the same type that was used as input. An example of that would be the mapBool function which takes a boolean value as input and then returns a string as output.

export const mapBool = (input: boolean[]): string[] =>Code language: JavaScript (javascript)

Honestly I couldn’t think of much else to do with an array of true / false values than convert them to string.

Err, filter? I Thought This Was A map‘ping Exercise?

Ahh, well, you got me.

There’s a reason for the ordering of these implementations being:

  • reduce
  • filter
  • map

Often times you may receive duff input when working with real world data.

null, empty strings, undefined, stuff like that.

A really useful technique is to first run your data through a filter operation to remove falsy values.

One of our challenges is:

  Given an array of one empty string
  When mapped
  Then the outcome should be an empty arrayCode language: Gherkin (gherkin)

We can first run a function to trim the given string, removing any leading and trailing white space.

At this point we either have a string with something in it, or an empty string – "" – which would be considered a false value in JavaScript / TypeScript.

export const mapString = (input: string[]): string[] =>
  input
    .map((string) => string.trim())
    .filter((string) => string)
    .map(
      (string) =>
        `${string[0].toUpperCase()}${string.substring(1).toLowerCase()}`
    );
Code language: JavaScript (javascript)

If after the first map on line 3 the value is an empty string, then line 4 will filter it out, and the process won’t continue for that element.

After that we make use of template strings, and the fact that we can index into a string to reference individual characters.

// get the first letter of the string
string[0] 

// convert the input to uppercase
string[0].toUpperCase()

// display the output in the template literal
${string[0].toUpperCase()}

// grab all the rest of the 'string' starting from character index 1
string.substring(1)


// another example


// concat things together
const a = "hello"
const b = "chris"

// output "hello from chris"
console.log(`${a} from ${b}`) Code language: JavaScript (javascript)

And that is it.

The actual implementation code from this exercise is pretty straightforward in my opinion. However, we needed to make use of filter as part of the flow, so that’s why this one ends up coming last.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.