In an order pipeline, how do a mapping stage and a filtering stage each change a collection's size and order?
answer
- two stages, two different shape contracts
- one changes values, the other changes count
- relative order survives both stages
- mapping: exactly one output per input
- filtering: a subset, source order kept
basics
~20 sA mapping stage produces exactly one output per input, so count and order are unchanged and only element values or types change. A filtering stage keeps a subset in the original relative order, so its count can only shrink.
solid answer
~50 sMapping is the shape-preserving stage. It applies a one-argument transform to every element and puts each result in the position its input held, so a thousand order lines in means a thousand shipment lines out, in the same order; only the value or the element type changes. Filtering is the shape-reducing stage. It applies a predicate — a function returning true or false — and keeps the accepted elements in the order they already had, so the count lands anywhere between zero and the input count while the element type is untouched. Neither stage reorders, and neither writes to the source collection: each hands back a new one. That gives a cheap review rule — if the count changed across a mapping stage, or the relative order changed across either, the stage is not the plain operation the code claims it is.
code
pseudocode · 12 linesfunction map(items, transform):
result = empty list
for each item in items:
append transform(item) to result // one output per input
return result
function filter(items, predicate):
result = empty list
for each item in items:
if predicate(item):
append item to result // a subset, same order
return resultgo deeper
Recall the two contracts in one line each: a mapping stage gives one output per input, a filtering stage gives a subset. Both keep the source's relative order, and neither writes to the source collection.
Explain the contracts from the function signatures: element-to-value for mapping, element-to-boolean for filtering. From those alone, derive why only one of the two stages can ever change the element count.
Use shape as a diagnostic in review. A count that moved across a mapping stage, or a result whose relative order changed, means the stage is doing something its name does not describe — usually hidden state or a side effect in the function.
When you set pipeline conventions for several teams, the value of these contracts is that a reader can predict a stage's shape without reading its function. A stage that quietly breaks that taxes every future reader of the code.
## What each stage promises A **mapping stage** is built from a collection and a one-argument **transform**: a function that takes one element and returns one value. The stage walks the collection and places `transform(element)` in the result at the position that element occupied. The promise has three parts: **exactly one output per input**, **in the same position**, and **every element visited once**. The element type is free to change completely — order lines go in, shipment lines come out — but the count and the ordering are dictated by the input, not by the transform. A **filtering stage** is built from a collection and a **predicate**: a function that takes one element and returns true or false. The stage walks the collection and keeps the elements the predicate accepted, **in the order they already had**. Its promise also has three parts: the result is a **subset** of the input, **relative order is preserved**, and the surviving elements are **not transformed**, so the element type is unchanged. The count lands anywhere between zero and the input count. | property | mapping stage | filtering stage | |---|---|---| | function it takes | element → value | element → true/false | | result count | equal to the input count | between zero and the input count | | relative order | preserved | preserved | | element type | may change | unchanged | | the source collection | read only | read only | ## Reading the order pipeline by its shape Take a pipeline that turns order lines into shipment lines and drops the cancelled ones. Because each stage's shape behaviour is fixed, you can state the count at every point without reading a single transform: 1. Start with 1,000 order lines. 2. Map each order line to a shipment line — **still 1,000**, in the same order, now a different element type. 3. Filter out the cancelled ones — **1,000 becomes however many survive**, say 830, and those 830 are in the relative order they had among the 1,000. 4. Map each survivor to a labelled shipment line — **still 830**, same order again. The only line in that trace where the count could move is the filtering stage. That is the practical payoff of the contract: shape is a property of *which stage* you used, not of *what the function does*. ## The mistakes the contract rules out - A mapping stage **cannot drop** an element. If the transform has nothing sensible to return for some input, it must still return something for that position. - A mapping stage **cannot reorder or sort**. It is positional by definition; sorting is a separate operation with a separate contract. - A filtering stage **cannot edit** the elements it keeps. A predicate is asked a yes/no question; anything it writes to the element is a side effect, not part of the stage. - A filtering stage **cannot change the element type** of the collection. Selection is not transformation. - Neither stage writes to the source collection. Each reads it and returns a new collection. - Neither stage removes duplicates. Two equal inputs produce two outputs in a mapping stage, and both survive or both fail a predicate that only looks at the element. ## Why interviewers open here These two stages are the first vocabulary anyone meets in a transformation pipeline, and the question separates a candidate who has memorised names from one who can reason about a pipeline they have not read. The reasoning is entirely mechanical once the contracts are stated, which is why it is a first-screen question rather than a deep one: given a chain of stages, you can compute the output count and the ordering guarantee by looking only at the stage names. It also sets up everything else in a pipeline. A stage that collapses the whole collection to one value, a stage that turns one element into many and then flattens, a stage that sorts — each is defined by contrast with these two. If you cannot say crisply that mapping preserves count and filtering preserves order, the follow-up questions have nowhere to stand. ## The reviewer's version of the same knowledge Once the contracts are internalised, they become a diagnostic. If a mapping stage's result has fewer elements than its input, the code is doing something the stage name does not describe — the transform is being called for its side effects, or the collection being appended to is not the one being returned. If a filtered result comes back in a different relative order, either something sorted it or the stage is not a plain filter. In both cases the shape mismatch is visible without understanding the business rule at all, which is exactly what makes it worth asking.
- A filtering stage accepts every element it sees. How does its result relate to the source collection?The result holds the same elements in the same order, but it is a separate collection — an eager filtering stage allocates and fills a new one even when nothing is rejected. Code that expects the source object itself back is relying on an optimisation no stage promises.
- You want shipment lines only for order lines that are not cancelled. Does it matter whether the filtering stage comes before or after the mapping stage?Not for the result, provided the predicate can be expressed on either element type. It matters for work: filtering first means the transform runs only on survivors and the intermediate collection is smaller. If the predicate needs a field that only the mapped element has, the filter cannot move.
Mapping is relabelling every parcel on a moving belt: same parcels, same order, new labels. Filtering is lifting some parcels off the belt without ever swapping the ones that remain.
saying these in an interview costs you the question
- Says a filtering stage can also change each surviving element's value.
- Thinks a mapping stage may drop inputs its transform has no answer for.
- Claims filtering returns elements in predicate-match order, not source order.
- Believes either stage edits the source collection in place.
- Assumes the mapped result must keep the input's element type.