R Lists Exercises: 10 Practice Problems with Full Solutions
Ten hands-on exercises on R lists, the most flexible data structure in the language. You will build, nest, subset with the tricky [ vs [[ rule, iterate with lapply/sapply, and convert between lists and data frames. Every problem runs in the browser.
A list in R can hold anything: numbers, strings, data frames, other lists, even functions. That flexibility makes lists both indispensable (every lm() result is a list) and confusing (two different subsetting operators that return different things). These exercises fix the confusion by forcing you to use both operators deliberately.
Setup
The code blocks share state across the whole page. We will build one list in Exercise 1 and keep using it.
Section 1, Create and inspect
Exercise 1. Build a heterogeneous list
Create a list called profile with four elements: name = "Ada", age = 37, skills = c("R", "Python", "SQL"), and employed = TRUE. Confirm its length and print its str().
Solution
Unlike a vector, a list does not coerce its elements to a common type. Each element keeps its own type.
Exercise 2. Inspect a built-in list (a linear model)
Fit m <- lm(mpg ~ wt, data = mtcars). Confirm that m is a list, report its class and its names.
Solution
Almost every model object in R is a list with a class attribute. Knowing this is why you can write m$coefficients or m$residuals directly.
Section 2, The [ vs [[ rule
Exercise 3. Predict the type
For the profile list, predict the class and length of each of the following before running them:
Solution
The rule: [ keeps the container (always returns a list), [[ extracts the contents (returns whatever is inside). $ is a shortcut for [[ that only accepts literal names.
Exercise 4. Modify an element
Change profile$age to 38, and append a new element city = "Brisbane" to the list.
Solution
Assigning to an index that does not exist creates the element. Setting it to NULL removes it: profile$city <- NULL.
Section 3, Nested lists
Exercise 5. Create a nested list
Create team as a list of three members. Each member is itself a list with name, role and years. Use any made-up values.
Solution
Each element of team is itself a list. team[[1]] extracts the first member (a list), then $name drills into it.
Exercise 6. Drill down two levels
From team, return (a) the name of the third member, (b) the role of the second member, and (c) a vector of all three members' years of experience.
Solution
sapply() walks the top-level list and applies a function to each element, simplifying the result to a vector. This is how you extract parallel columns from a list of lists.
Section 4, Iteration
Exercise 7. lapply on a list of numbers
Create nums <- list(a = 1:5, b = 6:10, c = 11:20). Use lapply() to compute the mean of each element, and sapply() to do the same thing and get a named vector.
Solution
lapply() always returns a list with the same length as its input. sapply() tries to simplify the list to a vector or matrix when every element has the same shape. When the shapes differ, sapply() quietly falls back to a list, so read your output.
Exercise 8. Apply with extra arguments
Using nums, use sapply() to compute the mean of each element ignoring the first value. Hint: you can pass extra arguments to the applied function.
Solution
The anonymous function gives you full control over what happens to each element. The \(x) form is the modern shorthand for function(x).
Section 5, Conversion and flattening
Exercise 9. Flatten to a vector
Convert nums (a list of numeric vectors) into a single flat numeric vector, then into a character vector with every element joined by ", ".
Solution
unlist() recursively flattens the list and attaches sensible names combining the list name and vector position. Use unlist(x, use.names = FALSE) if you do not want the names.
Exercise 10. Convert a list of records to a data frame
Convert team (a list of three lists with the same fields) into a data frame with one row per team member.
Solution
do.call(rbind.data.frame, team) is the base R one-liner for converting a list of equally shaped records into a data frame. For anything larger or messier, dplyr::bind_rows(team) handles mismatched fields gracefully.
Summary
- A list can hold elements of any type, including other lists, data frames and functions.
[returns a list (the container).[[and$return the element inside. This is the single most important rule about lists.- Build nested lists by passing lists as list elements. Drill down with chained
[[and$. lapply()always returns a list;sapply()simplifies when it can.- Flatten with
unlist(). Convert a list of records to a data frame withdo.call(rbind.data.frame, x)ordplyr::bind_rows(x).