# JavaScript Interview Exercises With Solutions 2019

March 23, 2019

I find it extremely beneficial to ask a job seeker to solve some of the following exercises. It helps to understand how good is a person you're dealing with in JavaScript and also shows how he or she thinks about the problems in general.

In this article, I'd like to share some of those exercises.

Just putting them here in no particular order. Feel free to use any of them in your next interview.

## What is `reduce`? Please implement the `map` and `filter` functions with `reduce`.

SOLUTION: `Array.proptotype.reduce` is a function on an array, which allows to iterate through the array and collect a result to return (which can be modified on each iteration). It takes a reducer function and an initial value for the accumulator.

``````const arr = [1, 2, 3];
arr.reduce((acc, el) => {
return el + acc;
}, 0); // => 15
``````

Here's how we can implement `map`:

``````function map(arr, mapper) {
return arr.reduce((acc, el) => {
return [...acc, mapper(el)];
}, []);
}
map([1, 2, 3], (x) => x * x); // => [1, 4, 9]
``````

And here's `filter`:

``````function filter(arr, f) {
return arr.reduce((acc, el) => (f(el) ? [...acc, el] : acc), []);
}
filter([-1, 0, 1, 2], (x) => x > 0); // => [1, 2]
``````

## Write the `uniq` function that removes repeated elements from the array.

SOLUTION:

``````function uniq(arr) {
return arr.reduce(
(acc, el) => (acc.indexOf(el) > -1 ? acc : [...acc, el]),
[]
);
}
uniq([1, 2, 3, 1, 2]); // => [1, 2, 3]
``````

An even shorter solution is possible if we utilize Set which can\t have non-unique members:

``````const uniq = (arr) => [...new Set(arr)];
``````

## `Flatten` is a function that puts elements from the inner arrays into the top array.

Can you implement `deepFlatten` so that

``````deepFlatten([1, , [, [4, ]]]); // => [1, 2, 3, 4, 5]
``````

SOLUTION:

``````function deepFlatten(arr) {
return arr.reduce(
(acc, el) =>
Array.isArray(el) ? [...acc, ...deepFlatten(el)] : [...acc, el],
[]
);
}
``````

## How many users per hobby?

Assuming we have an array of users

``````const users = [
{ name: "John", hobbies: ["singing", "walking", "playing guitar"] },
{ name: "Terry", hobbies: ["swimming", "playing guitar"] },
{ name: "Anna", hobbies: ["walking", "swimming", "playing guitar"] },
{ name: "Paul", hobbies: ["swimming", "singing"] },
];
``````

For each hobby, count the number of users occupied with it.

SOLUTION:

``````const hobbies = uniq(flatten(users.map(u => u.hobbies)))
const hasHobby = (h) => (u) => u.hobbies.indexOf(h) > -1
const counts hobbies.map( h => ({
hobby: h,
count: users.filter(hasHobby(h)).length,
})) // => [ {hobby: 'singing', count: 2}, ... ]
``````

SOLUTION 2 (Imperative):

``````const counts = {}

users.forEach(u => {
u.hobbies.forEach(h => {
counts[h] = (counts[h] || 0) + 1
})
})
``````

## Write a sample(arr, n) function that takes n random elements from an array.

SOLUTION:

``````function sample(arr, n) {
const length = arr.length
const indices = []
while(indices.length &lt; n){
const r = Math.floor(Math.random() * length);
if (indices.indexOf(r) === -1) indices.push(r);
}
return indices.map(i => arr[i])
}

sample([1, 2, 3, 4, 5, 6, 7, 8, 9], 3) // => [7, 9, 6]
``````

## Write a `memoize` function

It wraps a given function and only runs it once for a list of parameters, saves the result in inner cache and return it the next time.

SOLUTION (Basic):

``````function memoize(fn) {
const cache = {};
return function (...args) {
const key = args.join("-");
if (!cache[key]) {
cache[key] = fn(...args);
}
return cache[key];
};
}
``````

This solution is very simple. But it doesn’t work for some cases. We can make it more complex by asking: what if a function returns a boolean, what if a function is type-unsafe ( 1 vs “1” ), …

## Can you implement a function that will get a value from an object by logical path "a.b.c"?

...no matter how deep, and will return `null` if no value is there without throwing an exception.

Example:

``````safeGet({ a: { b: 5 } }, "a.b"); // => 5
``````

SOLUTION:

``````function safeGet(obj, path) {
const keys = path.split(".");
return keys.reduce((acc, key) => {
return (acc || {})[key] ? acc[key] : null;
}, obj);
}

safeGet({ a: { b: 5 } }, "a.b"); //=> 5

safeGet({ a: { b: 5 } }, "a.b.c.d"); //=> null
``````

## Currying is when you can call a function with only some arguments

...and it returns a new function which you can use with the rest of the arguments. Write the `curry` function.

Example:

``````sum(1, 2) // => 3
const addOne = sum(1)
addOne(2) // => 3
``````

SOLUTION:

``````function curry(fn, arity) {
arity = arity || fn.length
return function(...args) {
if (args.length &lt; arity) {
function f(...lefts) {
return fn(...args, ...lefts)
}
return curry(f, arity - args.length)
} else {
return fn(...args)
}
}
}

const sum = curry((a, b, c) => a + b + c)

sum(1, 2, 3) //=> 6
sum(1)(2, 3) //=> 6
sum(1, 2)(3) //=> 6
sum(1)(2)(3) //=> 6
``````