Lists

Reviewed & published by Brayan K

A list is R's flexible container — unlike a vector, it can hold values of different types and even nest other lists, vectors, or data frames inside it.

Part of the free R course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

By the end of this lesson you'll build lists with named elements, access them with $ and [[ ]], modify and extend them, and read nested structures with str().

What You'll Learn in This Lesson

1️⃣ Creating Lists

Build a list with list(), optionally naming each element with name = value. Elements can be any type — a number, a string, or a whole vector. Access named elements with the $ operator.

# A list can hold DIFFERENT types, unlike a vector. Build it with list().

person <- list(
  name = "Ada",
  age = 36,
  languages = c("R", "Python", "SQL")   # an element can be a whole vector
)

person$name          # access by name with $  -> [1] "Ada"
person$languages     # -> [1] "R"      "Python" "SQL"
length(person)       # number of elements -> [1] 3

2️⃣ [[ ]] vs [ ], and Editing

Use [[ ]] (or $) to pull out the actual element; [ ] returns a smaller list. Add or change elements simply by assigning to a name.

# Two bracket styles matter for lists:
# [[ ]] pulls out the ELEMENT itself; [ ] returns a smaller LIST.

scores <- list(math = 90, science = 85, art = 70)

scores[["math"]]     # the value -> [1] 90
scores$science       # same idea -> [1] 85
scores["math"]       # a length-1 LIST, not the number

# Add or change elements by assignment:
scores$music <- 88
names(scores)        # -> [1] "math"    "science" "art"     "music"

See how scores["math"] printed as $math followed by the value — that's a list wrapper. scores[["math"]] gave the bare number.

3️⃣ Nested Lists

Lists can contain lists, which lets you model structured records — an order with a customer who has their own fields. Drill in by chaining $ or [[ ]], and use str() to see the whole shape.

# Lists can nest — a list inside a list — which models real records well.

order <- list(
  id = 1001,
  customer = list(name = "Bob", vip = TRUE),
  items = c("pen", "notebook")
)

order$customer$name        # drill in with $  -> [1] "Bob"
order[["customer"]][["vip"]]  # or [[ ]]      -> [1] TRUE

# str() reveals the whole structure at a glance:
str(order)

Your turn. Fill in the ___ blank, run it, and compare with the expected output.

# 🎯 YOUR TURN — replace each ___ then run it.

# 1) Build a list describing a book: title, year, and a vector of authors
book <- list(
  title = "R Programming",
  year = 2023,
  authors = ___   # 👉 replace ___ with c("Lee", "Patel")
)

# 2) Print the title and the number of authors
cat("Title:", book$title, "\n")
cat("Authors:", length(book$authors), "\n")

# ✅ Expected output:
# Title: R Programming
# Authors: 2

Mini-Challenge: A Movie Record

Write it from the outline, run it, and check it against the example output. Practising add-by-assignment and $ access cements how lists work.

Common Errors (and the fix)

Pro Tips

📋 Quick Reference — Lists

TaskR Syntax
Create a listlist(a = 1, b = "x")
Get an elementlst$a or lst[["a"]]
Get a sublistlst["a"]
Add / changelst$c <- 3
Remove elementlst$a <- NULL
Inspect structurestr(lst)

🎉 Lesson Complete!

Practice quiz

What is the key difference between a list and a vector?

  • A list is always shorter
  • A list can hold elements of different types
  • A list cannot be named
  • A list holds only numbers

Answer: A list can hold elements of different types. Unlike a vector, a list can hold mixed types and even nested structures.

Which function creates a list?

  • c()
  • vector()
  • list()
  • data()

Answer: list(). Build a list with list(), optionally naming each element.

What does single-bracket lst["a"] return for a list?

  • A smaller list
  • The bare element
  • An error
  • NULL

Answer: A smaller list. Single [ ] returns a sublist; the element stays wrapped in a list.

Which extracts the actual element (the value itself)?

  • lst("a")
  • lst{"a"}
  • lst["a"]
  • lst[["a"]]

Answer: lst[["a"]]. Double brackets [[ ]] (or $) reach in and return the element itself.

How do you access a named element with the dollar operator?

  • person.name
  • person$name
  • person->name
  • person@name

Answer: person$name. The $ operator accesses a named list element, e.g. person$name.

How do you delete an element from a list?

  • Set it to NULL
  • Use drop()
  • Use remove()
  • Set it to NA

Answer: Set it to NULL. Assigning NULL, e.g. lst$a <- NULL, removes the element.

Which function reveals a list's nested structure at a glance?

  • dim()
  • summary()
  • str()
  • names()

Answer: str(). str() prints the structure of a list, including nesting.

What happens if you use $ on an atomic vector?

  • Returns the first element
  • Returns NULL silently
  • Works like on a list
  • Raises '$ operator is invalid for atomic vectors'

Answer: Raises '$ operator is invalid for atomic vectors'. $ only works on lists and data frames, not atomic vectors.

What does accessing a misspelled list name like person$naem return?

  • NULL
  • An error
  • The first element
  • NA

Answer: NULL. A misspelled name silently returns NULL; check names(person).

Why do many R functions return a list?

  • Lists print faster
  • Lists use less memory
  • Lists bundle differently-shaped parts in one object
  • Lists are required by R

Answer: Lists bundle differently-shaped parts in one object. A list neatly holds results of different lengths or types, like model output.

Continue this course

Frequently asked questions

What is the difference between a list and a vector in R?

A vector can only hold one type — all numbers, or all text, or all logicals. A list is far more flexible: each element can be a different type, and an element can itself be a vector, another list, a data frame, or even a function. Use a vector for a uniform column of values; use a list when you need to bundle together mixed pieces of information, like a record with a name, an age, and a list of hobbies.

When do I use [ ] versus [[ ]] on a list?

Single brackets [ ] return a sublist — a smaller list that still wraps its contents. Double brackets [[ ]] reach in and return the actual element (the value itself). So mylist[1] gives you a one-element list, while mylist[[1]] gives you the thing stored at position 1. As a rule: use [[ ]] (or $) to extract a single element you want to work with, and [ ] when you genuinely want a list back.

How do I access a list element by its name?

If a list has named elements, the cleanest way is the $ operator: person$name. You can also use double brackets with the name in quotes: person[["name"]] — which is handy when the name is stored in a variable. Both return the element itself. The $ form is the most readable for fixed names, while [[ ]] is more flexible for programmatic access.

Why do many R functions return lists?

Lists are the natural container when a result has several differently-shaped parts. For example, fitting a linear model returns a list containing coefficients, residuals, fitted values, and more — each a different length or type. Returning a list lets a function hand back everything in one tidy object that you can then pick apart with $. You'll see this pattern constantly once you start using statistical functions.