COMPUTER PROGRAMMING 1 (JAVASCRIPT) • PROBLEM SOLVING & MINI-PROJECTS

Transforming Datasets — I can transform a dataset (filter, map fields) and output results in a readable report.

Learn to filter, reshape, and display data using JavaScript's powerful array methods.

Historical Context & Motivation

Computers have always been about processing data — taking raw information, sifting through it, and presenting something useful. Before programming languages existed, people performed these tasks by hand: clerks would sort through paper records, pick out relevant entries, copy specific columns into a new ledger, and write up a summary report. The entire field of data transformation grew from the need to automate this tedious but essential work.

As programming languages evolved, developers created increasingly elegant ways to express these operations. JavaScript, originally designed for simple web page interactions in the mid-1990s, eventually gained powerful array methods that made data transformation concise and readable. Understanding the history of these tools helps you appreciate why modern JavaScript code for filtering and mapping looks the way it does.

1958
Lisp Introduces map and filter
John McCarthy's Lisp language introduced the idea of applying a function to every element of a list (map) and selecting elements that pass a test (filter). These concepts became foundational in computer science.
1995
JavaScript Is Born
Brendan Eich created JavaScript in ten days at Netscape. Early versions had basic array support but lacked the built-in transformation methods we use today.
2009
ES5 Adds .filter() and .map()
ECMAScript 5 standardized .filter() and .map() as built-in array methods, giving every JavaScript developer easy access to functional-style data transformation.
2015
ES6 Arrow Functions
Arrow functions (=>) made chaining .filter() and .map() calls much more concise and readable, fueling the modern JavaScript style.
2020s
Data Pipelines Everywhere
Today, transforming datasets is a core pattern in web apps, APIs, dashboards, and data science. JavaScript's array methods power millions of real-time interfaces that filter and display data from databases and APIs.

The central question this lesson addresses is straightforward: given an array of objects (a dataset), how do you select only the items you want, reshape each item to contain only the fields you need, and then produce a nicely formatted output? By the end of this lesson, you will be able to chain .filter() and .map() together and output a readable report to the console.

Core Principles & Definitions

Before diving into code, let's nail down the core ideas. A dataset in JavaScript is typically an array of objects, where each object represents one record — like one student, one product, or one game score. Transforming a dataset means taking that array and producing a new array (or a formatted string) that contains only the information you care about.

1

Dataset (Array of Objects)

A collection of records stored as an array. Each element is an object with key-value pairs representing fields like name, age, or score.
2

Filter (.filter())

A method that creates a new array containing only the elements that pass a test (a callback function that returns true or false).
3

Map (.map())

A method that creates a new array by applying a transformation function to every element. Use it to reshape objects — picking specific fields or computing new ones.
4

Chaining

Because both .filter() and .map() return new arrays, you can chain them: data.filter(...).map(...). This is a clean, readable pipeline.
5

Readable Report

The final step: formatting your transformed data into a human-friendly string or console output using template literals, console.table(), or a .join() call.
✦ KEY TAKEAWAY
Think of a dataset transformation like a cafeteria lunch line. Filter is the step where you skip the foods you don't want — you only grab what matches your criteria. Map is putting each chosen item on your tray in a specific arrangement — maybe you only take the fruit off the plate and leave the garnish behind. The report is you describing your tray to a friend in a clear sentence. The original buffet stays untouched — you always get a new tray.
💡 Non-Destructive Operations
Both .filter() and .map() are non-destructive — they never modify the original array. They always return a brand-new array. This means your source data stays safe no matter how many transformations you apply.

Visual Explanation — The Data Pipeline

The diagram below shows the flow of data through a typical filter-then-map pipeline. On the left you see the original dataset — five student records. The filter stage removes records that don't meet the condition (grade below 80), leaving three students. The map stage then reshapes each surviving record, extracting only the name and grade fields. Finally, the report presents the result as formatted text.

Data flows left to right: the original five-record dataset enters the filter stage (cyan), which removes records below 80. Survivors pass to the map stage (violet), which extracts only the desired fields. The result is formatted into a readable report (green).

Notice two important things in the diagram. First, the original dataset on the left is never modified — every stage produces a new array. Second, the .filter() callback returns true or false for each element (shown as ✓ and ✗), while the .map() callback returns a brand-new object for each element. This distinction is crucial: filter decides which items survive, and map decides what shape each surviving item takes.

How .filter() and .map() Work Under the Hood

Understanding the internal mechanics of .filter() and .map() makes the syntax click. Both methods follow the same basic pattern: iterate over every element in the array, call a callback function on each element, and use the callback's return value to build a new array. The difference is what each method does with the return value.

The .filter() Method

When you call array.filter(callback), JavaScript creates an empty result array, then loops through each element. For each element, it calls your callback. If the callback returns a truthy value, the element is pushed into the result array. If the callback returns a falsy value, the element is skipped. The method then returns the result array.

FILTER PATTERN
array.filter(element => condition)
element — each item in the array, one at a time. condition — a boolean expression. If true, the element is included in the new array. The original array is untouched.

The .map() Method

When you call array.map(callback), JavaScript creates an empty result array, loops through each element, calls your callback, and pushes whatever the callback returns into the result array. This is how you reshape data: your callback receives the old object and returns a new one with different fields, computed values, or formatted strings.

MAP PATTERN
array.map(element => newValue)
element — each item, one at a time. newValue — any expression. The result array will contain these new values in the same order. The result array always has the same length as the original.

Chaining: Filter Then Map

CHAIN PATTERN
array.filter(condition).map(transform)
First, .filter() produces a shorter array. Then .map() reshapes each remaining element. The chain reads like an English sentence: "Take my array, keep only items where condition is true, then transform each one."
⚠️ Order Matters
Always filter before you map when the filter condition uses fields that the map might remove. If you map first and strip out a field, you can no longer filter on it. Think of it like choosing which apples to keep before peeling them — you want to inspect them while they still have their skin.

Syntax Deep Dive — Callbacks, Arrow Functions & Template Literals

To use .filter() and .map() effectively, you need to be comfortable with three JavaScript features: callback functions, arrow function syntax, and template literals for building readable output. This section breaks each one down.

Top: The anatomy of an arrow function used with .filter(). The parameter (s) represents each element; the arrow (=>) leads to the body. Bottom: A template literal with backticks and ${} slots for embedding expressions directly into strings.
Key syntax features used when building data transformation pipelines
Syntax FeatureWhat It Looks LikeWhen to Use It
Regular functionfunction(s) { return s.grade >= 80; }When you want maximum clarity or need the this keyword.
Arrow function (concise)s => s.grade >= 80Single expression that returns a value — the most common form in filter/map.
Arrow function (block body)s => { const x = s.grade; return x >= 80; }When you need multiple statements inside the callback. Must include return explicitly.
Template literal`Name: ${s.name}`Building readable output strings with embedded variables — perfect for reports.
.join(separator)lines.join('\n')Combining an array of strings into one string with a separator between each element.

Worked Example — Building an Honor Roll Report

Let's walk through a complete example. Imagine you have a dataset of students, and you need to produce a report listing only students with grades of 80 or above, showing each student's name and grade in a clean, readable format.

Honor Roll Report
1
Step 1 — Define the DatasetStart by creating an array of student objects. Each object has three fields: name, grade, and club. const students = [ { name: "Ali", grade: 92, club: "Chess" }, { name: "Bo", grade: 67, club: "Art" }, { name: "Cam", grade: 85, club: "Drama" }, { name: "Dee", grade: 73, club: "Chess" }, { name: "Eve", grade: 91, club: "Band" } ];
5 student objects stored in students
2
Step 2 — Filter for Honor Roll (grade ≥ 80)Use .filter() with a callback that checks if the student's grade is 80 or higher. This returns a new array containing only qualifying students. const honorStudents = students.filter(s => s.grade >= 80);
Result: [{ name: "Ali", grade: 92, club: "Chess" }, { name: "Cam", grade: 85, club: "Drama" }, { name: "Eve", grade: 91, club: "Band" }] — 3 of 5 students pass the test.
3
Step 3 — Map to Extract Name and Grade OnlyThe report doesn't need the club field. Use .map() to create new objects with only name and grade. const reportData = honorStudents.map(s => ({ name: s.name, grade: s.grade }));
Result: [{ name: "Ali", grade: 92 }, { name: "Cam", grade: 85 }, { name: "Eve", grade: 91 }]
4
Step 4 — Format as Readable LinesUse .map() a second time to convert each object into a formatted string using a template literal. const lines = reportData.map(s => ` - ${s.name}: ${s.grade}`);
Result: [" - Ali: 92", " - Cam: 85", " - Eve: 91"]
5
Step 5 — Combine and Output the ReportJoin the lines into a single string with newlines and add a header. Then log it to the console. const report = `Honor Roll Report\n${lines.join('\n')}\n\nTotal: ${lines.length} students`; console.log(report);
Console output: Honor Roll Report - Ali: 92 - Cam: 85 - Eve: 91 Total: 3 students
🔗 Chaining All at Once
You can combine Steps 2–4 into one chained expression for a cleaner look: const lines = students .filter(s => s.grade >= 80) .map(s => ` - ${s.name}: ${s.grade}`); This does filtering and formatting in a single pipeline. Each method returns a new array, so the chain flows naturally from one step to the next.

filter/map vs. Other Approaches

You might wonder: can't you just use a for loop to do the same thing? Absolutely — but there are trade-offs. Understanding when to use .filter() and .map() versus a traditional loop or other methods will help you write cleaner, more maintainable code.

Comparing approaches for dataset transformation
ApproachStrengthsLimitations
.filter() + .map()Declarative and readable — each method has one job. Non-destructive. Easy to chain. Encourages clean, small callbacks.Iterates through the array twice (once for filter, once for map). Slightly less efficient on very large datasets (millions of items).
for loopFull control over iteration. Can filter and map in a single pass. Familiar to beginners.More verbose — requires manual array creation, pushing, and index management. Easier to introduce bugs.
.forEach()Runs a function on each element. Good for side effects like logging.Does not return a new array. You must manually push to an external array, which is less clean.
.reduce()Can do everything — filter, map, and accumulate — in a single pass.Harder to read, especially for beginners. Overkill for simple filter + map tasks.
✦ KEY TAKEAWAY
Use .filter() and .map() as your default approach for transforming datasets. Think of them as specialized tools in a toolbox: a wrench and a screwdriver each do one thing well, and using the right tool for each job makes your work clearer than a single Swiss Army knife (.reduce()) that tries to do everything at once. Switch to a for loop only when performance is critical or you need complex control flow.

Connection to Advanced Patterns

The filter-map-report pattern you've learned is the foundation of much more powerful data processing techniques. As you advance in programming, you'll encounter these same ideas applied at a much larger scale — in databases, APIs, and real-time applications.

How today's skills connect to advanced programming patterns
What You Learned TodayAdvanced Version
.filter() on an arrayWHERE clauses in SQL databases — same concept, different syntax
.map() to reshape objectsSELECT statements in SQL — choosing which columns to return
Chaining .filter().map()Functional programming pipelines in libraries like RxJS or data tools like Pandas (Python)
Console report with console.log()Rendering data in HTML tables, charts, or dashboards using React, Vue, or D3.js
Hardcoded dataset in your codeFetching live data from an API with fetch() and transforming the JSON response

You'll also encounter .sort() for ordering results, .reduce() for computing totals and averages, and .find() for locating a single record. These all follow the same callback pattern you've practiced here, so picking them up later will feel natural. The mental model of "pass a function to describe what I want" is the single most important idea to carry forward.

Practice Problems

Work through the following five problems to solidify your understanding of filtering, mapping, and report generation. Each problem builds on the skills from the lesson.

PROBLEM 1 — CONCEPTUAL
Explain in your own words: why does .filter() return a new array instead of modifying the original? What advantage does this give you as a programmer?
PROBLEM 2 — BASIC CALCULATION
Given the array const prices = [12, 5, 8, 25, 3, 18];, write a .filter() call that returns only prices above 10. What is the resulting array?
PROBLEM 3 — INTERMEDIATE
Given const books = [ { title: "1984", pages: 328, genre: "fiction" }, { title: "Cosmos", pages: 365, genre: "science" }, { title: "Dune", pages: 412, genre: "fiction" }, { title: "Brief History", pages: 256, genre: "science" } ];, write a chain that filters for science books and maps each to a string in the format "Title (X pages)". What does the final array look like?
PROBLEM 4 — APPLIED
You have a dataset of products: const products = [ { name: "Laptop", price: 999, inStock: true }, { name: "Mouse", price: 25, inStock: false }, { name: "Monitor", price: 350, inStock: true }, { name: "Keyboard", price: 75, inStock: true }, { name: "Webcam", price: 60, inStock: false } ];. Write code that: (1) filters for products that are in stock, (2) maps each to an object with only name and a new field priceLabel formatted as "$999", and (3) outputs a multi-line report to the console.
PROBLEM 5 — CRITICAL THINKING
A classmate writes the following code and complains that the filter doesn't work — it returns an empty array even though some games have ratings above 4. Can you find and explain the bug? const games = [ { title: "Zelda", rating: 4.8 }, { title: "Mario", rating: 4.5 }, { title: "Pong", rating: 3.2 } ]; const topGames = games .map(g => g.title) .filter(g => g.rating > 4);

Lesson Summary

In this lesson you learned how to transform a dataset — an array of objects — using JavaScript's built-in array methods. The .filter() method accepts a callback that returns true or false and produces a new array containing only the elements that passed the test. The .map() method accepts a callback that transforms each element and returns a new array of the same length. Both methods are non-destructive — the original array is never modified.

By chaining these methods — data.filter(...).map(...) — you can build clean data pipelines that select, reshape, and format records in a readable way. To produce a readable report, use template literals with backticks and ${} expression slots, then combine lines with .join('\n'). Remember the golden rule: always filter before you map when the filter condition depends on fields that the map might remove. These skills form the foundation for database queries, API data handling, and front-end rendering that you'll encounter as you advance in programming.

Varsity Tutors • Computer Programming 1 (JavaScript) • Transforming Datasets — I can transform a dataset (filter, map fields) and output results in a readable report.