javascript

exercises

exercises.js
/**
 * =====================================================
 * 4.5 FOR...OF AND FOR...IN LOOPS - EXERCISES
 * =====================================================
 * Practice specialized iteration
 */

/**
 * Exercise 1: Sum Array
 *
 * Calculate the sum of all numbers in an array using for...of.
 */
function sumArray(numbers) {
  // TODO: Use for...of to sum all numbers
}

// Test cases:
console.log('Exercise 1:');
console.log(sumArray([1, 2, 3, 4, 5])); // 15
console.log(sumArray([10, 20, 30])); // 60
console.log(sumArray([])); // 0

/**
 * Exercise 2: Find Maximum
 *
 * Find the maximum value in an array using for...of.
 */
function findMax(numbers) {
  // TODO: Use for...of to find the maximum
}

// Test cases:
console.log('\nExercise 2:');
console.log(findMax([3, 7, 2, 9, 5])); // 9
console.log(findMax([-5, -2, -8])); // -2
console.log(findMax([42])); // 42

/**
 * Exercise 3: Count Characters
 *
 * Count occurrences of each character in a string using for...of.
 * Return an object with character counts.
 */
function countCharacters(str) {
  // TODO: Use for...of to count each character
}

// Test cases:
console.log('\nExercise 3:');
console.log(countCharacters('hello'));
// { h: 1, e: 1, l: 2, o: 1 }
console.log(countCharacters('aabbcc'));
// { a: 2, b: 2, c: 2 }

/**
 * Exercise 4: Get Object Keys
 *
 * Return an array of all own property keys using for...in.
 * Don't include inherited properties.
 */
function getOwnKeys(obj) {
  // TODO: Use for...in with hasOwnProperty
}

// Test cases:
console.log('\nExercise 4:');
const parent = { inherited: true };
const child = Object.create(parent);
child.own1 = 'a';
child.own2 = 'b';
console.log(getOwnKeys(child)); // ["own1", "own2"]
console.log(getOwnKeys({ x: 1, y: 2, z: 3 })); // ["x", "y", "z"]

/**
 * Exercise 5: Object Values Sum
 *
 * Sum all numeric values in an object.
 */
function sumObjectValues(obj) {
  // TODO: Use for...in or Object methods
}

// Test cases:
console.log('\nExercise 5:');
console.log(sumObjectValues({ a: 10, b: 20, c: 30 })); // 60
console.log(sumObjectValues({ x: 5, y: 'text', z: 15 })); // 20 (skip non-numbers)

/**
 * Exercise 6: First Duplicate
 *
 * Find the first duplicate element in an array using for...of.
 * Return undefined if no duplicates.
 */
function firstDuplicate(arr) {
  // TODO: Use for...of with a Set to track seen values
}

// Test cases:
console.log('\nExercise 6:');
console.log(firstDuplicate([1, 2, 3, 2, 4])); // 2
console.log(firstDuplicate([1, 2, 3, 4])); // undefined
console.log(firstDuplicate(['a', 'b', 'a'])); // "a"

/**
 * Exercise 7: Map from Entries
 *
 * Create a Map from an array of key-value pairs using for...of.
 */
function createMap(entries) {
  // TODO: Build a Map from entries array
}

// Test cases:
console.log('\nExercise 7:');
const map1 = createMap([
  ['a', 1],
  ['b', 2],
  ['c', 3],
]);
console.log(map1.get('b')); // 2
console.log(map1.size); // 3

/**
 * Exercise 8: Filter Object
 *
 * Create a new object with only properties that pass the predicate.
 */
function filterObject(obj, predicate) {
  // TODO: Filter object properties using for...in
  // predicate(value, key) returns true to include
}

// Test cases:
console.log('\nExercise 8:');
const nums = { a: 1, b: 2, c: 3, d: 4 };
console.log(filterObject(nums, (v) => v > 2)); // { c: 3, d: 4 }
console.log(filterObject(nums, (v, k) => k !== 'b')); // { a: 1, c: 3, d: 4 }

/**
 * Exercise 9: Flatten Array
 *
 * Flatten a 2D array into a 1D array using for...of.
 */
function flatten(arr2d) {
  // TODO: Flatten using nested for...of
}

// Test cases:
console.log('\nExercise 9:');
console.log(
  flatten([
    [1, 2],
    [3, 4],
    [5, 6],
  ])
); // [1, 2, 3, 4, 5, 6]
console.log(flatten([['a'], ['b', 'c'], ['d']])); // ["a", "b", "c", "d"]

/**
 * Exercise 10: Merge Objects
 *
 * Merge multiple objects into one. Later objects override earlier ones.
 */
function mergeObjects(...objects) {
  // TODO: Merge all objects using for...of and for...in
}

// Test cases:
console.log('\nExercise 10:');
console.log(mergeObjects({ a: 1 }, { b: 2 }, { c: 3 }));
// { a: 1, b: 2, c: 3 }
console.log(mergeObjects({ a: 1, b: 2 }, { b: 3, c: 4 }));
// { a: 1, b: 3, c: 4 }

// =====================================================
// BONUS CHALLENGES
// =====================================================

/**
 * Bonus 1: Group By Property
 *
 * Group an array of objects by a specified property.
 */
function groupBy(arr, property) {
  // TODO: Group objects by the given property
}

console.log('\nBonus 1:');
const people = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 25 },
];
console.log(groupBy(people, 'age'));
// { 25: [{name: "Alice"...}, {name: "Charlie"...}], 30: [{name: "Bob"...}] }

/**
 * Bonus 2: Deep Flatten
 *
 * Flatten an arbitrarily nested array.
 */
function deepFlatten(arr) {
  // TODO: Recursively flatten
}

console.log('\nBonus 2:');
console.log(deepFlatten([1, [2, [3, [4]], 5]])); // [1, 2, 3, 4, 5]

/**
 * Bonus 3: Object Difference
 *
 * Find properties that exist in obj1 but not in obj2,
 * or have different values.
 */
function objectDiff(obj1, obj2) {
  // TODO: Find differences
}

console.log('\nBonus 3:');
console.log(objectDiff({ a: 1, b: 2, c: 3 }, { a: 1, c: 4 }));
// { b: 2, c: 3 } (b is missing in obj2, c has different value)

// =====================================================
// SOLUTIONS (Uncomment to check your answers)
// =====================================================

/*
// Exercise 1 Solution:
function sumArray(numbers) {
    let sum = 0;
    for (const num of numbers) {
        sum += num;
    }
    return sum;
}

// Exercise 2 Solution:
function findMax(numbers) {
    if (numbers.length === 0) return undefined;
    let max = numbers[0];
    for (const num of numbers) {
        if (num > max) max = num;
    }
    return max;
}

// Exercise 3 Solution:
function countCharacters(str) {
    const counts = {};
    for (const char of str) {
        counts[char] = (counts[char] || 0) + 1;
    }
    return counts;
}

// Exercise 4 Solution:
function getOwnKeys(obj) {
    const keys = [];
    for (const key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            keys.push(key);
        }
    }
    return keys;
}

// Exercise 5 Solution:
function sumObjectValues(obj) {
    let sum = 0;
    for (const key in obj) {
        if (typeof obj[key] === "number") {
            sum += obj[key];
        }
    }
    return sum;
}

// Exercise 6 Solution:
function firstDuplicate(arr) {
    const seen = new Set();
    for (const item of arr) {
        if (seen.has(item)) {
            return item;
        }
        seen.add(item);
    }
    return undefined;
}

// Exercise 7 Solution:
function createMap(entries) {
    const map = new Map();
    for (const [key, value] of entries) {
        map.set(key, value);
    }
    return map;
}

// Exercise 8 Solution:
function filterObject(obj, predicate) {
    const result = {};
    for (const key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            if (predicate(obj[key], key)) {
                result[key] = obj[key];
            }
        }
    }
    return result;
}

// Exercise 9 Solution:
function flatten(arr2d) {
    const result = [];
    for (const row of arr2d) {
        for (const item of row) {
            result.push(item);
        }
    }
    return result;
}

// Exercise 10 Solution:
function mergeObjects(...objects) {
    const result = {};
    for (const obj of objects) {
        for (const key in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, key)) {
                result[key] = obj[key];
            }
        }
    }
    return result;
}

// Bonus 1 Solution:
function groupBy(arr, property) {
    const groups = {};
    for (const item of arr) {
        const key = item[property];
        if (!groups[key]) {
            groups[key] = [];
        }
        groups[key].push(item);
    }
    return groups;
}

// Bonus 2 Solution:
function deepFlatten(arr) {
    const result = [];
    for (const item of arr) {
        if (Array.isArray(item)) {
            for (const nested of deepFlatten(item)) {
                result.push(nested);
            }
        } else {
            result.push(item);
        }
    }
    return result;
}

// Bonus 3 Solution:
function objectDiff(obj1, obj2) {
    const diff = {};
    for (const key in obj1) {
        if (!(key in obj2) || obj1[key] !== obj2[key]) {
            diff[key] = obj1[key];
        }
    }
    return diff;
}
*/
Exercises - JavaScript Tutorial | DeepML