Topic 13: Operators on Collections
📖 6 min read · 🎯 advanced · 🧭 Prerequisites: custom-ui-components, application-architecture-using-mvcmvpmvvm-each-topic-covered-on-one-day
Why this matters
Up until now, you've been storing data in lists and arrays — but storing data is only half the job. The real work is shaping it: pulling out only what you need, transforming every item, finding a specific one, or collapsing a whole list into a single answer. Think about the last time you scrolled through a food-delivery app and filtered by "under 30 minutes" or sorted by rating — that's exactly what operators like filter, map, sort, and reduce do under the hood. In this lesson, you'll learn to stop looping through collections by hand and start using Kotlin's built-in operators to do that work cleanly and in far fewer lines.
What You'll Learn
- Apply JavaScript array methods (
forEach,map,filter,reduce,find,some,every,sort,reverse) to transform and query collections - Apply equivalent Python operations using built-ins (
map,filter,reduce,any,all,sorted,reversed) and generator expressions - Recognize the structural similarities between JavaScript and Python collection operators
- Identify the key differences in how each language exposes these operations (prototype methods vs. built-in functions)
The Analogy
Think of a collection as a conveyor belt in a factory full of products rolling past. forEach is a worker who inspects every item but changes nothing. map is a spray-painter who repaints each item and puts a brand-new version on a second belt. filter is a quality inspector who only lets certain items through the gate. reduce is an accountant at the end of the line who tallies everything into one final number. find is the first inspector who raises a hand the moment a qualifying item rolls by and stops watching after that. sort and reverse are the logistics crew who reorder the belt entirely before it even starts moving.
Chapter 1: Operators on Collections in JavaScript
JavaScript arrays ship with a rich set of prototype methods that let you express data transformations declaratively. Create a file called collections.js and work through each method below.
collections.js
// Example array
let numbers = [1, 2, 3, 4, 5];
// forEach: Executes a function for each element — no return value
numbers.forEach((number) => {
console.log(number);
});
// map: Creates a new array with the results of calling a function on every element
let squares = numbers.map((number) => number * number);
console.log(squares); // [1, 4, 9, 16, 25]
// filter: Creates a new array with all elements that pass the test
let evenNumbers = numbers.filter((number) => number % 2 === 0);
console.log(evenNumbers); // [2, 4]
// reduce: Executes a reducer function on each element, resulting in a single output value
let sum = numbers.reduce((total, number) => total + number, 0);
console.log(sum); // 15
// find: Returns the first element that passes the test
let firstEvenNumber = numbers.find((number) => number % 2 === 0);
console.log(firstEvenNumber); // 2
// some: Checks if at least one element passes the test
let hasNegativeNumbers = numbers.some((number) => number < 0);
console.log(hasNegativeNumbers); // false
// every: Checks if all elements pass the test
let allPositive = numbers.every((number) => number > 0);
console.log(allPositive); // true
// sort: Sorts the elements of an array — spread first to avoid mutating the original
let sortedNumbers = [...numbers].sort((a, b) => b - a);
console.log(sortedNumbers); // [5, 4, 3, 2, 1]
// reverse: Reverses the order of the elements in an array
let reversedNumbers = [...numbers].reverse();
console.log(reversedNumbers); // [5, 4, 3, 2, 1]
Run the file:
node collections.js
Method reference at a glance
| Method | Returns | Mutates original? |
|---|---|---|
forEach | undefined | No |
map | New array | No |
filter | New array (subset) | No |
reduce | Single value | No |
find | First match or undefined | No |
some | Boolean | No |
every | Boolean | No |
sort | Sorted array (in-place!) | Yes — spread first |
reverse | Reversed array (in-place!) | Yes — spread first |
sortandreversemutate the original array by default. The spread operator ([...numbers]) creates a shallow copy so the source array stays intact — a critical habit in production code.
Chapter 2: Operators on Collections in Python
Python achieves the same results through a combination of built-in functions, the functools module, and generator expressions. Create collections.py and walk through each operation.
collections.py
# Example list
numbers = [1, 2, 3, 4, 5]
# forEach equivalent: Iterating through each element with a for loop
for number in numbers:
print(number)
# map: Creating a new list with the results of calling a function on every element
squares = list(map(lambda x: x * x, numbers))
print(squares) # [1, 4, 9, 16, 25]
# filter: Creating a new list with all elements that pass the test
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # [2, 4]
# reduce: Applying a reducer function to each element, resulting in a single output value
from functools import reduce
sum_of_numbers = reduce(lambda total, x: total + x, numbers)
print(sum_of_numbers) # 15
# find: Finding the first element that passes the test
# Uses next() with a generator expression; returns None if nothing matches
first_even_number = next((x for x in numbers if x % 2 == 0), None)
print(first_even_number) # 2
# some equivalent: Checking if at least one element passes the test (using any)
has_negative_numbers = any(x < 0 for x in numbers)
print(has_negative_numbers) # False
# every equivalent: Checking if all elements pass the test (using all)
all_positive = all(x > 0 for x in numbers)
print(all_positive) # True
# sort: Sorting the elements of a list — sorted() returns a new list, does not mutate
sorted_numbers = sorted(numbers, reverse=True)
print(sorted_numbers) # [5, 4, 3, 2, 1]
# reverse: Reversing the order of the elements in a list
reversed_numbers = list(reversed(numbers))
print(reversed_numbers) # [5, 4, 3, 2, 1]
Run the file:
python collections.py
Key Python idioms to remember
map()andfilter()return iterators in Python 3 — wrap them inlist()to get a concrete list.reduceis not a built-in in Python 3; import it fromfunctools.sorted()always returns a new list; the original is untouched. This is the opposite default from JavaScript'sArray.prototype.sort.reversed()returns an iterator; wrap inlist()to materialize it.- Generator expressions (
x for x in numbers if ...) are Python's idiomatic, lazy alternative tofilter— pair withnext()for afind-style lookup.
Chapter 3: Comparing JavaScript and Python Collection Operators
the trainer pulled up a side-by-side chart on the chamber screen to close out the session.
Similarities
- Both JavaScript and Python offer ways to iterate over every element in a collection (
forEachin JavaScript; aforloop in Python). - Both provide
map— create a new collection by applying a transformation function to each element. - Both provide
filter— produce a sub-collection containing only elements that satisfy a condition. - Both provide
reduce— aggregate a collection down to a single value using an accumulator. - Both languages support sorting and reversing collections.
Differences
- JavaScript exposes
find,some, andeverydirectly as array prototype methods. Python usesnext()with a generator expression forfind, and the built-in functionsany()/all()forsome/every. - JavaScript's
Array.prototype.sortandArray.prototype.reversemutate the original array. Python'ssorted()andreversed()are non-mutating and return new objects. - Python's
reducelives infunctools(not a built-in), reflecting the language's preference for explicitforloops over functional reduction chains. - Python's
mapandfilterreturn lazy iterators; JavaScript's return fully realized arrays immediately.
graph LR
subgraph JavaScript
J1[forEach] --> J2[map]
J2 --> J3[filter]
J3 --> J4[reduce]
J4 --> J5[find / some / every]
J5 --> J6[sort / reverse — mutates!]
end
subgraph Python
P1[for loop] --> P2[map + list]
P2 --> P3[filter + list]
P3 --> P4[reduce from functools]
P4 --> P5[next + generator / any / all]
P5 --> P6[sorted / reversed — non-mutating]
end
J1 -.equivalent.- P1
J2 -.equivalent.- P2
J3 -.equivalent.- P3
J4 -.equivalent.- P4
J5 -.equivalent.- P5
J6 -.equivalent.- P6
🧪 Try It Yourself
Task: Given the array/list [3, 17, -4, 9, 0, -1, 42, 8], produce two results:
- A new collection containing only the positive numbers (strictly greater than 0), each squared.
- The sum of those squared positives.
Success criterion: Running your file should print [9, 289, 81, 1764, 64] and 2207 to the console (order may vary depending on language sort behavior — the sum is the canonical check).
JavaScript starter:
const data = [3, 17, -4, 9, 0, -1, 42, 8];
const squaredPositives = data
.filter((n) => n > 0)
.map((n) => n * n);
const total = squaredPositives.reduce((acc, n) => acc + n, 0);
console.log(squaredPositives);
console.log(total);
Python starter:
from functools import reduce
data = [3, 17, -4, 9, 0, -1, 42, 8]
squared_positives = list(map(lambda x: x * x, filter(lambda x: x > 0, data)))
total = reduce(lambda acc, x: acc + x, squared_positives)
print(squared_positives)
print(total)
🔍 Checkpoint Quiz
Q1. In JavaScript, why should you write [...numbers].sort(...) instead of numbers.sort(...) when you want to keep the original array intact?
A) sort returns undefined without the spread
B) sort mutates the array in place; spreading creates a shallow copy first
C) The spread operator is required syntax for the comparator callback
D) sort only works on copies of arrays, never originals
Q2. What does the following Python snippet print?
data = [10, 3, 7, 1, 9]
result = next((x for x in data if x < 5), -1)
print(result)
A) 1
B) 3
C) -1
D) [3, 1]
Q3. Given this JavaScript code, what is the value of output?
const values = [2, 4, 6, 8];
const output = values.every((v) => v % 2 === 0);
A) [2, 4, 6, 8]
B) 4
C) false
D) true
Q4. You have a Python list of order totals and need to flag whether any order exceeds $500. Which built-in best fits this task, and why?
A) all() — it confirms every order is valid
B) any() — it short-circuits and returns True the moment one match is found
C) filter() — it returns all matching orders
D) next() — it returns the first exceeding value
A1. B — Array.prototype.sort mutates the array in place. Spreading into a new array first ensures the source collection is unchanged, which is essential when the original order still matters downstream.
A2. B — The generator expression yields 3 as the first element less than 5. next() returns it immediately without scanning the rest of the list.
A3. D — every returns true only if the callback returns true for all elements. All four values are even, so output is true.
A4. B — any() is the idiomatic choice. It short-circuits on the first True result, making it efficient even on large datasets. filter() would work but materializes all matches unnecessarily when you only need a boolean answer.
🪞 Recap
- JavaScript arrays expose
forEach,map,filter,reduce,find,some,every,sort, andreversedirectly as prototype methods. - Python achieves the same results via built-in functions (
map,filter,any,all,sorted,reversed),functools.reduce, and generator expressions withnext(). - JavaScript's
sortandreversemutate the original array; Python'ssorted()andreversed()are non-mutating — a critical behavioral difference. - Both languages share the same conceptual model: iterate, transform, filter, aggregate, find, check, reorder.
- Mastering these operators is foundational for writing clean, declarative data-manipulation code in any collection-heavy application.
📚 Further Reading
- MDN Array methods reference — authoritative source for every JavaScript array prototype method
- Python Built-in Functions — map, filter, any, all — official Python docs covering the built-ins used in this lesson
- Python functools.reduce — official docs for
reduceincluding examples and the identity argument - Eloquent JavaScript — Chapter 5: Higher-Order Functions — deep dive into functional collection transforms in JavaScript
- ⬅️ Previous: Application Architecture Using MVC/MVP/MVVM
- ➡️ Next: Mini Project 1 — Week Duration Until Launch in the Play Store