We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Closures and Iterators step 9 of 28
map, filter, filter_map: parse host:port lines
Extract ports from text lines using one filter_map closure.
pub fn parse_ports(lines: Vec<String>) -> Vec<u16>
For each line:
- Split at the first
:. Skip the line if there is no colon. - Parse the entire remainder as a decimal
u16. Skip it if parsing fails. - Keep the number only if it is at least 1024.
Return accepted ports in input order, including duplicates. Invalid lines produce no output element. An empty input returns an empty vector.
The host portion is ignored and may be empty. This is a text-parsing exercise, not a hostname validator or a general network-address parser. Do not trim either portion or add IPv6 handling. The threshold of 1024 is an exercise rule, not a check that a port is available on your machine.
| Input line | Result | Reason |
|---|---|---|
localhost:8080 |
Keep 8080 | Valid number above the threshold. |
h:1024 |
Keep 1024 | The threshold is inclusive. |
example.com:80 |
Skip | Below the threshold. |
:8080 |
Keep 8080 | An empty host is allowed. |
x:08080 or x:+8080 |
Keep 8080 | Leading zeroes and a leading plus are accepted. |
h:65535 |
Keep 65535 | Largest u16 value. |
h:65536 or h:-1 |
Skip | Outside the accepted unsigned range. |
h: 8080 or h:8080 |
Skip | Port whitespace is not trimmed. |
a:b:c or a::8080 |
Skip | The remainder after the first colon is not a number. |
bad or h: |
Skip | Missing colon or empty port. |
For example, ["localhost:8080", "example.com:80", "bad", "a:b"]
produces [8080].
Choose an adapter that retains the parsed value
| Adapter | Closure result | Effect when fully consumed |
|---|---|---|
map |
A value U |
Produce one result for every input item. |
filter |
A bool |
Keep matching items without changing their type. |
filter_map |
An Option<U> |
Keep the value inside each Some; omit each None. |
filter and filter_map can keep every item, some items, or none. They do
not necessarily reduce the count. filter_map fits this task because parsing
both decides whether a line is usable and produces the number to keep.
Use ? to skip an invalid line
Inside an Option-returning closure, ? unwraps a Some or returns None
from that closure. It does not return from parse_ports or stop the iterator.
split_once(':') already returns an Option. Parsing returns a Result,
so use .ok() to convert success into Some and an error into None.
The error details are deliberately discarded because this task only returns
valid ports.
Here is a complete example of the same pattern for plain numbers:
fn main() {
let numbers: Vec<u16> = ["12", "bad", "34"]
.into_iter()
.filter_map(|text| {
let number: u16 = text.parse().ok()?;
Some(number + 1)
})
.collect();
assert_eq!(numbers, [13, 35]);
}
For the port threshold, (port >= 1024).then_some(port) produces Some(port)
when the condition is true and None otherwise. then_some evaluates its
argument eagerly. Use then(|| ...) when a computation should run only if
the condition is true; returning an already-computed port needs no closure.
Give parsing a target type
parse can produce many types. Its target must be supplied explicitly or
inferred from surrounding code. Either of these bindings works inside the
closure:
let port: u16 = text.parse().ok()?;
let port = text.parse::<u16>().ok()?;
The ::<u16> syntax is often called the turbofish. A standalone binding
such as let port = "8080".parse(); has no information identifying the
intended parsed type and causes a type-inference error.
Simplify the starter
The starter's is_some/unwrap and is_ok/unwrap stages produce the
requested output, but Clippy rejects those patterns with warnings denied.
In this exact pipeline the preceding filters make the unwraps safe.
Combining selection and extraction makes that relationship easier to follow.
Replace the stages with a single filter_map closure containing the split,
parse and threshold checks, then collect the accepted values. Avoid an
unwrap in that closure: missing or invalid ports are expected input here.
A passing submission must compile, pass the tests, and pass
clippy -D warnings. The single-closure structure is an exercise requirement;
output checks and lints do not establish every aspect of implementation style.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.