Module 6: JavaScript Array Methods & Collections

Modules 1–5 solved everything with plain loops on purpose, so the underlying logic was never hidden behind a shortcut. This module is the payoff: the functional Array methods JavaScript developers reach for daily — map, filter, reduce, find, some/every, forEach, sort — plus the Set and Map collection types, each one matched against its closest Python idiom.

Module 6 of 12 Problems 51–60 JS + Python ~45–60 Min

By the end of this module, you'll be able to

  • Pick the right Array method for the job — transform (map), keep (filter), collapse (reduce), or just look (find/some/every)
  • Chain filtermapreduce into a single readable pipeline
  • Translate each JS method to its nearest Python equivalent — comprehension, built-in, or plain loop

1. Problems 51–60

Same format as the previous modules: expand a problem to see the approach and both commented solutions.

Why Python's side sometimes looks different on purpose

JavaScript's Array methods are the idiomatic way to transform data — reaching for them is normal, everyday code. Python has direct equivalents (map(), filter(), functools.reduce()), but idiomatic Python usually prefers a list/generator comprehension or a built-in like sum()/any()/sorted() instead. Both versions are shown below so you can recognize either style.

P51

Double Every Number With map()

[1, 2, 3, 4] → [2, 4, 6, 8].

Approach: .map() takes a function and applies it to every element, returning a new array of the exact same length — one output for every input, always.

JavaScript
double-all.js
// .map() transforms each element and returns a new array of the same length.
function doubleAll(numbers) {
  return numbers.map((n) => n * 2); // n => new value, one in, one out
}

console.log(doubleAll([1, 2, 3, 4])); // [2, 4, 6, 8]
Python
double_all.py
def double_all(numbers: list) -> list:
    """map() applies a function to every item; list() collects the results."""
    return list(map(lambda n: n * 2, numbers))
    # Idiomatic Python: a list comprehension -> [n * 2 for n in numbers]

print(double_all([1, 2, 3, 4]))  # [2, 4, 6, 8]
P52

Keep Only Even Numbers With filter()

[1,2,3,4,5,6] → [2, 4, 6].

Approach: .filter() takes a function that returns true/false and keeps only the elements where it returned true — the output can be shorter than the input, unlike .map().

JavaScript
keep-evens.js
// .filter() keeps only elements where the callback returns true.
function keepEvens(numbers) {
  return numbers.filter((n) => n % 2 === 0);
}

console.log(keepEvens([1, 2, 3, 4, 5, 6])); // [2, 4, 6]
Python
keep_evens.py
def keep_evens(numbers: list) -> list:
    """filter() keeps only items where the function returns a truthy value."""
    return list(filter(lambda n: n % 2 == 0, numbers))
    # Idiomatic Python: [n for n in numbers if n % 2 == 0]

print(keep_evens([1, 2, 3, 4, 5, 6]))  # [2, 4, 6]
P53

Sum a List With reduce()

[1,2,3,4,5] → 15, folded down to one value.

Approach: .reduce() carries an accumulator through every element, combining each one with the running total — the same job problem 33's manual loop did, generalized into a reusable shape.

JavaScript
sum-with-reduce.js
// .reduce() folds a list down to a single value, carrying an accumulator forward.
function sumWithReduce(numbers) {
  return numbers.reduce((total, n) => total + n, 0); // 0 is the starting accumulator
}

console.log(sumWithReduce([1, 2, 3, 4, 5])); // 15
Python
sum_with_reduce.py
from functools import reduce

def sum_with_reduce(numbers: list) -> int:
    """reduce() folds a list down to a single value, carrying an accumulator forward."""
    return reduce(lambda total, n: total + n, numbers, 0)  # 0 is the starting accumulator
    # Idiomatic Python: sum(numbers)

print(sum_with_reduce([1, 2, 3, 4, 5]))  # 15
P54

Find the First Match With find()

The first number over 5 in [3,7,1,9,4] is 7.

Approach: .find() returns the first element itself that matches (not its index — that's .findIndex()), or undefined if nothing matches. It stops scanning the moment it finds a match.

JavaScript
first-over.js
// .find() returns the first matching element itself, or undefined if none match.
function firstOver(numbers, threshold) {
  return numbers.find((n) => n > threshold);
}

console.log(firstOver([3, 7, 1, 9, 4], 5)); // 7
Python
first_over.py
def first_over(numbers: list, threshold: int):
    """A generator expression + next() mirrors .find(): stop at the first match."""
    return next((n for n in numbers if n > threshold), None)  # None if nothing matches

print(first_over([3, 7, 1, 9, 4], 5))  # 7
P55

Check Any/All With some() and every()

[4,8,-2,6]: at least one negative, but not all positive.

Approach: .some() short-circuits true the moment one element passes; .every() short-circuits false the moment one element fails. Both stop scanning early instead of always checking every element.

JavaScript
check-list.js
// .some() is true if AT LEAST ONE element passes; .every() needs ALL of them to.
function checkList(numbers) {
  const hasNegative = numbers.some((n) => n < 0);
  const allPositive = numbers.every((n) => n > 0);
  return { hasNegative, allPositive };
}

console.log(checkList([4, 8, -2, 6])); // { hasNegative: true, allPositive: false }
Python
check_list.py
def check_list(numbers: list) -> dict:
    """any() is true if AT LEAST ONE element passes; all() needs ALL of them to."""
    has_negative = any(n < 0 for n in numbers)
    all_positive = all(n > 0 for n in numbers)
    return {"has_negative": has_negative, "all_positive": all_positive}

print(check_list([4, 8, -2, 6]))  # {'has_negative': True, 'all_positive': False}
P56

Sort a List of Objects by a Property

Sort three people by age, youngest first.

Approach: JS's .sort() mutates the array in place and takes a comparator (negative → a comes first, positive → b comes first) — spread into a copy first if the original order matters. Python's sorted() always returns a new list and takes a key function instead of a comparator.

JavaScript
sort-by-age.js
// .sort() mutates in place and takes a comparator: negative -> a first, positive -> b first.
function sortByAge(people) {
  return [...people].sort((a, b) => a.age - b.age); // copy first so the original stays untouched
}

const people = [{ name: "Amit", age: 32 }, { name: "Riya", age: 24 }, { name: "Sam", age: 28 }];
console.log(sortByAge(people).map((p) => p.name)); // ["Riya", "Sam", "Amit"]
Python
sort_by_age.py
def sort_by_age(people: list) -> list:
    """sorted() returns a new list; key= picks what to compare instead of a comparator."""
    return sorted(people, key=lambda p: p["age"])

people = [{"name": "Amit", "age": 32}, {"name": "Riya", "age": 24}, {"name": "Sam", "age": 28}]
print([p["name"] for p in sort_by_age(people)])  # ['Riya', 'Sam', 'Amit']
P57

Chain filter + map + reduce Into a Pipeline

Total value of every in-stock item, in one expression.

Approach: chaining reads as a pipeline, left to right: filter down to what qualifies, map each surviving item to the number you actually need, then reduce those numbers into one total. This is the same three-problem pattern from P51–P53, composed.

JavaScript
total-in-stock-value.js
// Chaining reads as a pipeline: filter what qualifies, map to the value you need,
// reduce that down to one number.
function totalInStockValue(items) {
  return items
    .filter((item) => item.inStock)
    .map((item) => item.price * item.qty)
    .reduce((total, lineTotal) => total + lineTotal, 0);
}

const items = [
  { name: "Pen", price: 10, qty: 3, inStock: true },
  { name: "Mug", price: 150, qty: 2, inStock: false },
  { name: "Bag", price: 500, qty: 1, inStock: true },
];
console.log(totalInStockValue(items)); // 530
Python
total_in_stock_value.py
def total_in_stock_value(items: list) -> float:
    """The same pipeline, written as a generator expression fed straight into sum()."""
    return sum(item["price"] * item["qty"] for item in items if item["in_stock"])

items = [
    {"name": "Pen", "price": 10, "qty": 3, "in_stock": True},
    {"name": "Mug", "price": 150, "qty": 2, "in_stock": False},
    {"name": "Bag", "price": 500, "qty": 1, "in_stock": True},
]
print(total_in_stock_value(items))  # 530
P58

forEach for Side Effects

Print every item with its index — no new array involved.

Approach: .forEach() always returns undefined — it exists purely for side effects like printing or logging, never for building a new array. Reaching for .map() when you don't use its return value is a common beginner mix-up worth avoiding.

JavaScript
print-indexed.js
// .forEach() runs a function for each element but always returns undefined --
// use it for side effects (like printing), never to build a new list.
function printIndexed(items) {
  items.forEach((item, index) => {
    console.log(`${index}: ${item}`);
  });
}

printIndexed(["apple", "banana", "cherry"]);
// 0: apple
// 1: banana
// 2: cherry
Python
print_indexed.py
def print_indexed(items: list) -> None:
    """Python has no forEach() -- a plain for loop (often with enumerate) does the job."""
    for index, item in enumerate(items):
        print(f"{index}: {item}")

print_indexed(["apple", "banana", "cherry"])
# 0: apple
# 1: banana
# 2: cherry
P59

Deduplicate a List With Set

[1,2,2,3,3,3,4] → [1, 2, 3, 4], no manual loop needed.

Approach: a Set can only ever hold unique values — constructing one from an array automatically drops duplicates. Compare this to Module 3, Problem 23, which built the exact same behavior by hand with a loop and a helper set.

JavaScript
unique-values.js
// The Set constructor drops duplicates automatically; spreading it back into an
// array gives you a plain array again.
function uniqueValues(items) {
  return [...new Set(items)];
}

console.log(uniqueValues([1, 2, 2, 3, 3, 3, 4])); // [1, 2, 3, 4]
Python
unique_values.py
def unique_values(items: list) -> list:
    """set() drops duplicates the same way; list() converts it back to a list.
    Note: unlike Module 3's version, this does NOT preserve the original order."""
    return list(set(items))

print(sorted(unique_values([1, 2, 2, 3, 3, 3, 4])))  # [1, 2, 3, 4]
P60

Word Frequency Count With Map

Count how often each word appears, using JS's Map type.

Approach: the counting logic is identical to Module 1's character-frequency problem — the only difference is storing it in a Map instead of a plain object. A Map keeps insertion order and allows any value (not just strings) as a key, which a plain object can't guarantee.

JavaScript
word-frequency.js
// A Map keeps insertion order and allows any value as a key -- here it's used
// just like the frequency objects from Module 1, but as its own data structure.
function wordFrequency(words) {
  const freq = new Map();
  for (const word of words) {
    freq.set(word, (freq.get(word) || 0) + 1);
  }
  return freq;
}

const freq = wordFrequency(["cat", "dog", "cat", "bird", "dog", "cat"]);
console.log(freq.get("cat")); // 3
console.log([...freq.entries()]); // [["cat", 3], ["dog", 2], ["bird", 1]]
Python
word_frequency.py
def word_frequency(words: list) -> dict:
    """A plain dict already keeps insertion order in modern Python -- there's no
    separate 'Map' type the way JavaScript has one."""
    freq = {}
    for word in words:
        freq[word] = freq.get(word, 0) + 1
    return freq

freq = word_frequency(["cat", "dog", "cat", "bird", "dog", "cat"])
print(freq["cat"])          # 3
print(list(freq.items()))   # [('cat', 3), ('dog', 2), ('bird', 1)]

2. Key Takeaways

  • Pick the method by what shape you need back: map (same length, transformed), filter (shorter, same items), reduce (one final value), find/some/every (a single answer about the list), forEach (no return value at all — side effects only).
  • A chain of filtermapreduce is the same computation as a single manual loop with an if-check, an accumulator, and a running total — it's just organized as named, reusable steps instead.
  • Python leans on comprehensions and built-ins (sum, any, all, sorted) where JavaScript reaches for a named Array method — different syntax, same underlying idea.