javascript
exercises
exercises.js⚡javascript
/**
* =====================================================
* 5.7 HIGHER-ORDER FUNCTIONS - EXERCISES
* =====================================================
* Practice with functions that take/return functions
*/
/**
* Exercise 1: Basic map()
*
* Use map to transform the array.
*/
console.log('Exercise 1: Basic map()');
const numbers = [1, 2, 3, 4, 5];
// TODO: Create an array of squares
// const squares = numbers.map(???);
// console.log(squares); // [1, 4, 9, 16, 25]
// TODO: Create an array of strings
// const strings = numbers.map(???);
// console.log(strings); // ["1", "2", "3", "4", "5"]
/**
* Exercise 2: map() with Objects
*
* Extract and transform data from objects.
*/
console.log('\nExercise 2: map() with Objects');
const users = [
{ firstName: 'Alice', lastName: 'Smith', age: 25 },
{ firstName: 'Bob', lastName: 'Jones', age: 30 },
{ firstName: 'Charlie', lastName: 'Brown', age: 35 },
];
// TODO: Extract full names
// const fullNames = users.map(???);
// console.log(fullNames); // ["Alice Smith", "Bob Jones", "Charlie Brown"]
// TODO: Create summary objects { name, age }
// const summaries = users.map(???);
// console.log(summaries);
/**
* Exercise 3: filter()
*
* Filter arrays based on conditions.
*/
console.log('\nExercise 3: filter()');
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// TODO: Get odd numbers
// const odds = nums.filter(???);
// console.log(odds); // [1, 3, 5, 7, 9]
// TODO: Get numbers greater than 5
// const large = nums.filter(???);
// console.log(large); // [6, 7, 8, 9, 10]
/**
* Exercise 4: filter() with Objects
*
* Filter objects based on properties.
*/
console.log('\nExercise 4: filter() with Objects');
const products = [
{ name: 'Laptop', price: 999, inStock: true },
{ name: 'Phone', price: 699, inStock: false },
{ name: 'Tablet', price: 499, inStock: true },
{ name: 'Watch', price: 299, inStock: true },
];
// TODO: Get products in stock
// const available = products.filter(???);
// TODO: Get products under $500 that are in stock
// const cheapAvailable = products.filter(???);
/**
* Exercise 5: reduce() - Sum and Count
*
* Use reduce to calculate values.
*/
console.log('\nExercise 5: reduce()');
const values = [10, 20, 30, 40, 50];
// TODO: Calculate sum
// const sum = values.reduce(???);
// console.log(sum); // 150
// TODO: Calculate average
// const avg = values.reduce(???) / values.length;
// console.log(avg); // 30
/**
* Exercise 6: reduce() - Object Transformation
*
* Transform array to object.
*/
console.log('\nExercise 6: reduce() - Object Transformation');
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
// TODO: Count occurrences
// const counts = fruits.reduce(???);
// console.log(counts); // { apple: 3, banana: 2, orange: 1 }
const items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
];
// TODO: Create lookup object by id
// const lookup = items.reduce(???);
// console.log(lookup); // { 1: { id: 1, name: "Item 1" }, ... }
/**
* Exercise 7: find() and findIndex()
*
* Find specific elements.
*/
console.log('\nExercise 7: find() and findIndex()');
const employees = [
{ id: 101, name: 'Alice', department: 'Engineering' },
{ id: 102, name: 'Bob', department: 'Sales' },
{ id: 103, name: 'Charlie', department: 'Engineering' },
];
// TODO: Find employee with id 102
// const bob = employees.find(???);
// TODO: Find index of first Engineering employee
// const engIndex = employees.findIndex(???);
/**
* Exercise 8: some() and every()
*
* Test array conditions.
*/
console.log('\nExercise 8: some() and every()');
const scores = [75, 82, 90, 68, 95];
// TODO: Check if any score is perfect (100)
// const hasPerfect = scores.some(???);
// TODO: Check if all scores are passing (>= 60)
// const allPassing = scores.every(???);
/**
* Exercise 9: Method Chaining
*
* Chain methods for complex operations.
*/
console.log('\nExercise 9: Method Chaining');
const transactions = [
{ type: 'credit', amount: 1000 },
{ type: 'debit', amount: 200 },
{ type: 'credit', amount: 500 },
{ type: 'debit', amount: 100 },
{ type: 'credit', amount: 250 },
];
// TODO: Get total of credits
// const totalCredits = transactions
// .filter(???)
// .map(???)
// .reduce(???);
// console.log(totalCredits); // 1750
/**
* Exercise 10: sort()
*
* Sort arrays using comparison functions.
*/
console.log('\nExercise 10: sort()');
const people = [
{ name: 'Charlie', age: 35 },
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
];
// TODO: Sort by age (ascending)
// const byAge = [...people].sort(???);
// TODO: Sort by name (alphabetical)
// const byName = [...people].sort(???);
// =====================================================
// INTERMEDIATE EXERCISES
// =====================================================
/**
* Exercise 11: Custom Higher-Order Function
*
* Create a repeat function.
*/
console.log('\nExercise 11: Custom Higher-Order Function');
function repeat(n, action) {
// TODO: Execute action n times with index as argument
}
// Test:
// repeat(3, i => console.log(`Iteration ${i}`));
// Should print: Iteration 0, Iteration 1, Iteration 2
/**
* Exercise 12: Function Factory
*
* Create a function that returns functions.
*/
console.log('\nExercise 12: Function Factory');
function createGreeter(greeting) {
// TODO: Return a function that takes name and returns greeting message
}
// Test:
// const sayHello = createGreeter("Hello");
// const sayHi = createGreeter("Hi");
// console.log(sayHello("Alice")); // "Hello, Alice!"
// console.log(sayHi("Bob")); // "Hi, Bob!"
/**
* Exercise 13: Implement myMap
*
* Create your own map function.
*/
console.log('\nExercise 13: Implement myMap');
function myMap(array, transform) {
// TODO: Implement map functionality
}
// Test:
// console.log(myMap([1, 2, 3], n => n * 2)); // [2, 4, 6]
/**
* Exercise 14: Implement myFilter
*
* Create your own filter function.
*/
console.log('\nExercise 14: Implement myFilter');
function myFilter(array, predicate) {
// TODO: Implement filter functionality
}
// Test:
// console.log(myFilter([1, 2, 3, 4, 5], n => n > 2)); // [3, 4, 5]
/**
* Exercise 15: Pipe Function
*
* Create a pipe function that chains function calls.
*/
console.log('\nExercise 15: Pipe Function');
function pipe(...fns) {
// TODO: Return function that applies fns left to right
}
// Test:
// const process = pipe(
// n => n + 1,
// n => n * 2,
// n => n - 3
// );
// console.log(process(5)); // ((5 + 1) * 2) - 3 = 9
// =====================================================
// ADVANCED EXERCISES
// =====================================================
/**
* Bonus Exercise 1: Group By
*
* Create a groupBy function.
*/
console.log('\nBonus 1: Group By');
function groupBy(array, keyFn) {
// TODO: Group array elements by key function result
}
// Test:
// const grouped = groupBy(
// [{ type: 'a', val: 1 }, { type: 'b', val: 2 }, { type: 'a', val: 3 }],
// item => item.type
// );
// console.log(grouped);
// { a: [{ type: 'a', val: 1 }, { type: 'a', val: 3 }], b: [...] }
/**
* Bonus Exercise 2: Compose
*
* Create a compose function (right to left).
*/
console.log('\nBonus 2: Compose');
function compose(...fns) {
// TODO: Return function that applies fns right to left
}
// Test:
// const calc = compose(
// n => n - 3,
// n => n * 2,
// n => n + 1
// );
// console.log(calc(5)); // (((5) + 1) * 2) - 3 = 9
/**
* Bonus Exercise 3: Memoize
*
* Create a memoize function for caching results.
*/
console.log('\nBonus 3: Memoize');
function memoize(fn) {
// TODO: Return memoized version of fn
}
// Test:
// let callCount = 0;
// const expensiveFn = memoize((n) => {
// callCount++;
// return n * 2;
// });
// expensiveFn(5); // Computed
// expensiveFn(5); // Cached
// console.log(callCount); // 1
/**
* Bonus Exercise 4: Flatten
*
* Flatten nested arrays to specified depth.
*/
console.log('\nBonus 4: Flatten');
function flatten(array, depth = 1) {
// TODO: Flatten array to specified depth
}
// Test:
// console.log(flatten([1, [2, [3, [4]]]], 1)); // [1, 2, [3, [4]]]
// console.log(flatten([1, [2, [3, [4]]]], 2)); // [1, 2, 3, [4]]
// console.log(flatten([1, [2, [3, [4]]]], Infinity)); // [1, 2, 3, 4]
/**
* Bonus Exercise 5: Partition
*
* Split array into two based on predicate.
*/
console.log('\nBonus 5: Partition');
function partition(array, predicate) {
// TODO: Return [matching, notMatching]
}
// Test:
// const [evens, odds] = partition([1, 2, 3, 4, 5], n => n % 2 === 0);
// console.log(evens); // [2, 4]
// console.log(odds); // [1, 3, 5]
// =====================================================
// SOLUTIONS (Uncomment to check your answers)
// =====================================================
/*
// Exercise 1 Solution:
const squares = numbers.map(n => n * n);
const strings = numbers.map(n => String(n));
// Exercise 2 Solution:
const fullNames = users.map(u => `${u.firstName} ${u.lastName}`);
const summaries = users.map(u => ({ name: `${u.firstName} ${u.lastName}`, age: u.age }));
// Exercise 3 Solution:
const odds = nums.filter(n => n % 2 !== 0);
const large = nums.filter(n => n > 5);
// Exercise 4 Solution:
const available = products.filter(p => p.inStock);
const cheapAvailable = products.filter(p => p.price < 500 && p.inStock);
// Exercise 5 Solution:
const sum = values.reduce((acc, n) => acc + n, 0);
const avg = values.reduce((acc, n) => acc + n, 0) / values.length;
// Exercise 6 Solution:
const counts = fruits.reduce((acc, fruit) => {
acc[fruit] = (acc[fruit] || 0) + 1;
return acc;
}, {});
const lookup = items.reduce((acc, item) => {
acc[item.id] = item;
return acc;
}, {});
// Exercise 7 Solution:
const bob = employees.find(e => e.id === 102);
const engIndex = employees.findIndex(e => e.department === "Engineering");
// Exercise 8 Solution:
const hasPerfect = scores.some(s => s === 100);
const allPassing = scores.every(s => s >= 60);
// Exercise 9 Solution:
const totalCredits = transactions
.filter(t => t.type === "credit")
.map(t => t.amount)
.reduce((sum, a) => sum + a, 0);
// Exercise 10 Solution:
const byAge = [...people].sort((a, b) => a.age - b.age);
const byName = [...people].sort((a, b) => a.name.localeCompare(b.name));
// Exercise 11 Solution:
function repeat(n, action) {
for (let i = 0; i < n; i++) {
action(i);
}
}
// Exercise 12 Solution:
function createGreeter(greeting) {
return function(name) {
return `${greeting}, ${name}!`;
};
}
// Exercise 13 Solution:
function myMap(array, transform) {
const result = [];
for (const item of array) {
result.push(transform(item));
}
return result;
}
// Exercise 14 Solution:
function myFilter(array, predicate) {
const result = [];
for (const item of array) {
if (predicate(item)) {
result.push(item);
}
}
return result;
}
// Exercise 15 Solution:
function pipe(...fns) {
return function(value) {
return fns.reduce((acc, fn) => fn(acc), value);
};
}
// Bonus 1 Solution:
function groupBy(array, keyFn) {
return array.reduce((acc, item) => {
const key = keyFn(item);
if (!acc[key]) acc[key] = [];
acc[key].push(item);
return acc;
}, {});
}
// Bonus 2 Solution:
function compose(...fns) {
return function(value) {
return fns.reduceRight((acc, fn) => fn(acc), value);
};
}
// Bonus 3 Solution:
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key] === undefined) {
cache[key] = fn(...args);
}
return cache[key];
};
}
// Bonus 4 Solution:
function flatten(array, depth = 1) {
if (depth < 1) return array.slice();
return array.reduce((acc, item) => {
if (Array.isArray(item)) {
return acc.concat(flatten(item, depth - 1));
}
return acc.concat(item);
}, []);
}
// Bonus 5 Solution:
function partition(array, predicate) {
return array.reduce((acc, item) => {
acc[predicate(item) ? 0 : 1].push(item);
return acc;
}, [[], []]);
}
*/