Top 20 JavaScript Coding Challenges – Arrays, Strings & Logic (2025)

Strengthen your problem-solving skills with this curated list of 20 JavaScript code challenges covering array transformations, string manipulation, custom function implementations like debounce/throttle, and logic building. These problems are perfect for frontend interviews and coding assessments in 2025.

Medium

  • 1. Group elements by frequency

    Use reduce to count how many times each value appears in the array.

    const arr = [1, 2, 2, 3];
    const freq = arr.reduce((acc, val) => {
      acc[val] = (acc[val] || 0) + 1;
      return acc;
    }, {});
    console.log(freq); // {1:1, 2:2, 3:1}
  • 2. Flatten array without .flat()

    Use recursion with reduce and concat to flatten nested arrays.

    function flatten(arr) {
      return arr.reduce((acc, val) =>
        Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), []);
    }
    console.log(flatten([1, [2, [3]], 4])); // [1, 2, 3, 4]
  • 3. Find intersection of two arrays

    Filter values from one array that also exist in the other.

    const arr1 = [1, 2, 3];
    const arr2 = [2, 3, 4];
    const result = arr1.filter(x => arr2.includes(x));
    console.log(result); // [2, 3]
  • 4. Remove falsy values

    Falsy values include false, 0, '', null, undefined, and NaN.

    const arr = [0, 1, false, 2, '', 3];
    console.log(arr.filter(Boolean)); // [1, 2, 3]
  • 5. Chunk an array

    Split an array into groups of a specific size using Array.from and slice.

    function chunk(arr, size) {
      return Array.from({ length: Math.ceil(arr.length / size) }, (_, i) =>
        arr.slice(i * size, i * size + size));
    }
    console.log(chunk([1, 2, 3, 4, 5], 2)); // [[1, 2], [3, 4], [5]]
  • 6. Find most frequent element

    Track how often each value appears and then find the one with the max frequency.

    function mostFrequent(arr) {
      const freq = {};
      arr.forEach(val => freq[val] = (freq[val] || 0) + 1);
      return Object.keys(freq).reduce((a, b) => freq[a] > freq[b] ? a : b);
    }
    console.log(mostFrequent([1, 2, 2, 3, 3, 3])); // "3"
  • 7. Get all permutations of a string

    Recursively build all possible orderings by fixing one char and permuting the rest.

    function permute(str) {
      if (str.length <= 1) return [str];
      let result = [];
      for (let i = 0; i < str.length; i++) {
        let rest = str.slice(0, i) + str.slice(i + 1);
        for (let p of permute(rest)) result.push(str[i] + p);
      }
      return result;
    }
    console.log(permute("abc")); // ["abc", "acb", "bac", "bca", "cab", "cba"]
  • 8. Implement debounce

    Ensure a function runs only after a delay since the last time it was invoked.

    function debounce(fn, delay) {
      let timer;
      return function (...args) {
        clearTimeout(timer);
        timer = setTimeout(() => fn.apply(this, args), delay);
      };
    }
    const log = debounce(() => console.log("Hello"), 500);
  • 9. Implement throttle

    Throttle limits how frequently a function is called, even if triggered often.

    function throttle(fn, delay) {
      let last = 0;
      return function (...args) {
        let now = Date.now();
        if (now - last > delay) {
          fn.apply(this, args);
          last = now;
        }
      };
    }
    const log = throttle(() => console.log("Hello"), 1000);
  • 10. Remove duplicate objects from array

    Use JSON.stringify to compare objects and filter out duplicates.

    const arr = [
      { id: 1, name: "a" },
      { id: 2, name: "b" },
      { id: 1, name: "a" }
    ];
    const unique = arr.filter(
      (v, i, a) => a.findIndex(t => JSON.stringify(t) === JSON.stringify(v)) === i
    );
    console.log(unique);
    // [ { id: 1, name: "a" }, { id: 2, name: "b" } ]
  • 11. Implement custom map()

    Create your own version of the Array.prototype.map method.

    Array.prototype.myMap = function (cb) {
      let result = [];
      for (let i = 0; i < this.length; i++) {
        result.push(cb(this[i], i, this));
      }
      return result;
    };
    console.log([1, 2, 3].myMap(x => x * 2)); // [2, 4, 6]
  • 12. Convert nested object to flat

    Recursively convert a deeply nested object into a flat one with dot-separated keys.

    function flattenObj(obj, prefix = '', res = {}) {
      for (let key in obj) {
        let path = prefix ? `${prefix}.${key}` : key;
        typeof obj[key] === 'object' && obj[key] !== null
          ? flattenObj(obj[key], path, res)
          : res[path] = obj[key];
      }
      return res;
    }
    console.log(flattenObj({ a: { b: { c: 1 } } })); // {"a.b.c": 1}
  • 13. Check deep equality

    Compare two values deeply by serializing them to JSON strings.

    function isEqual(a, b) {
      return JSON.stringify(a) === JSON.stringify(b);
    }
    console.log(isEqual({ x: 1 }, { x: 1 })); // true
  • 14. Find longest word in sentence

    Split the string and use reduce to find the word with the most characters.

    const str = "Find the longest word here";
    const longest = str.split(' ').reduce((a, b) => a.length > b.length ? a : b);
    console.log(longest); // "longest"
  • 15. Sum of even numbers in array

    Filter even numbers and sum them using reduce.

    const arr = [1, 2, 3, 4, 5, 6];
    const sum = arr.filter(n => n % 2 === 0).reduce((a, b) => a + b, 0);
    console.log(sum); // 12
  • 16. Find all pairs that sum to a target

    Store seen values in a Set and check for complements.

    function pairSum(arr, target) {
      let seen = new Set(), pairs = [];
      for (let num of arr) {
        let comp = target - num;
        if (seen.has(comp)) pairs.push([num, comp]);
        seen.add(num);
      }
      return pairs;
    }
    console.log(pairSum([1, 2, 3, 4], 5)); // [[3,2], [4,1]]
  • 17. Count character frequency

    Use reduce to count how often each character appears.

    const str = "hello";
    const freq = [...str].reduce((acc, ch) => ((acc[ch] = acc[ch] + 1 || 1), acc), {});
    console.log(freq); // {h:1, e:1, l:2, o:1}
  • 18. Rotate array by K

    Rotate the array by slicing and rejoining it.

    function rotate(arr, k) {
      k = k % arr.length;
      return [...arr.slice(-k), ...arr.slice(0, -k)];
    }
    console.log(rotate([1, 2, 3, 4, 5], 2)); // [4, 5, 1, 2, 3]
  • 19. Convert Roman numeral to integer

    Check value of current symbol and next symbol to decide add or subtract.

    function romanToInt(s) {
      const map = {I:1,V:5,X:10,L:50,C:100,D:500,M:1000};
      let total = 0;
      for (let i = 0; i < s.length; i++) {
        const val = map[s[i]];
        const next = map[s[i+1]];
        total += val < next ? -val : val;
      }
      return total;
    }
    console.log(romanToInt("XIV")); // 14
  • 20. Get second largest number

    Remove duplicates, sort in descending order, and pick the second item.

    const arr = [10, 20, 10, 30, 20];
    const secondLargest = [...new Set(arr)].sort((a, b) => b - a)[1];
    console.log(secondLargest); // 20