Watch the video (9 min)
On this page23 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. What Is an Index?
  5. 2. Reading an Element
  6. 3. The Last Index Is length - 1
  7. 4. first and last
  8. 5. Replacing an Element
  9. 6. Replacements Are Type-Checked
  10. 7. RangeError: an Index That Doesn't Exist
  11. 8. Visiting Every Index with a for Loop
  12. 9. Finding a Position with indexOf
  13. 10. Nullable Elements vs a Nullable List
  14. 11. A Real-World Example
  15. Code Examples
  16. Common Beginner Mistakes
  17. Best Practices
  18. Mini Challenge
  19. Practice Questions
  20. Practice Answers
  21. Quick Revision
  22. Key Takeaways
  23. What's Next?

Lecture 40 — List Elements & Indexes

Category7 — Lists
Lecture040 of 140
Estimated video length9 min
TargetDart 3.12.2
LevelBeginner

A for-in loop hands you every value, but never "just the second one". Indexes let you reach any single element of a list directly — to read it, or to replace it.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways

Every error message in this lecture is real. Each one was produced by running the code shown on Dart 3.12.2, so you will recognize it when you meet it yourself.


Prerequisites

Students should already understand, from Lectures 001–039:

  • string indexes and length (Lecture 008)
  • nullable types and ?? (Lectures 013–014)
  • the counting for loop and the for-in loop (Lectures 026–027)
  • creating a List<T>, length, and isEmpty (Lecture 039)

Connection With Previous Lectures

In Lecture 039, we created lists and walked through them:

dart
void main() {
  var marks = [85, 92, 78];
  for (final mark in marks) {
    print(mark);
  }
}
output
85
92
78

Now suppose we want only Sara's mark, the second one. Or the teacher rechecks a paper and the 78 should be 80. A for-in loop cannot do either: it visits every value and its loop variable is a copy. We need a way to point at one position in the list.


Learning Objectives

By the end of this lecture you will be able to:

  • Explain zero-based indexing
  • Read any element with list[index]
  • Use first, last, and length - 1
  • Replace an element by assigning to list[index]
  • Recognize and avoid a RangeError
  • Visit every index with a counting for loop
  • Find a value's position with indexOf
  • Tell List<int?> apart from List<int>?

1. What Is an Index?

Every element in a list sits at a numbered position called its index. Counting starts at 0, exactly as with the characters of a string in Lecture 008.

Analogy — think of a row of lockers at school. Each locker has a number painted on it. To open one, you don't walk past all the others — you go straight to its number.

Index012
Element859278

2. Reading an Element

Write the index in square brackets after the list's name:

dart
void main() {
  var marks = [85, 92, 78];
  print(marks[0]);
  print(marks[1]);
  print(marks[2]);
}
output
85
92
78

marks[1] is the second element, because the first one is at index 0. The index can be any int expression, such as a variable or i + 1.


3. The Last Index Is length - 1

A list of 3 elements has indexes 0, 1, and 2. The last index is always one less than the length:

dart
void main() {
  var names = ['Ali', 'Sara', 'Zayan'];
  print(names.length);
  print(names[names.length - 1]);
}
output
3
Zayan

names.length - 1 keeps working when the list grows or shrinks; a fixed names[2] does not.


4. first and last

Reading the ends of a list is so common that every list has two shortcuts:

dart
void main() {
  var temperatures = [21.5, 25.0, 19.0];
  print(temperatures.first);
  print(temperatures.last);
}
output
21.5
19.0

first is the same as [0], and last the same as [length - 1] — just easier to read.


5. Replacing an Element

Put list[index] on the left of = to store a new value at that position:

dart
void main() {
  var marks = [85, 92, 78];
  marks[2] = 80;
  print(marks);
}
output
[85, 92, 80]

The list keeps its length; only the value at index 2 changes. Unlike a string (Lecture 008), a list can be changed in place. Compound operators work too: marks[0] += 5; adds 5 to the first mark.


6. Replacements Are Type-Checked

A List<int> holds only int values, so the new value must be an int:

dart
void main() {
  var marks = [85, 92, 78];
  marks[0] = 90.5;
  print(marks);
}
output
Error: A value of type 'double' can't be assigned to a variable of type 'int'.
  marks[0] = 90.5;
             ^

Each position behaves like a variable of the list's element type.


7. RangeError: an Index That Doesn't Exist

Ask for a position the list doesn't have, and the program compiles — then crashes when it runs:

dart
void main() {
  var marks = [85, 92, 78];
  print(marks[3]);
}
output
Unhandled exception:
RangeError (length): Invalid value: Not in inclusive range 0..2: 3

Read it piece by piece: the valid indexes are 0..2, and we asked for 3. Negative indexes fail the same way — marks[-1] reports Not in inclusive range 0..2: -1. Dart has no "count from the end" index; use last instead. Assigning to a missing position, such as marks[3] = 60;, also throws a RangeError: []= replaces, it never adds. Adding new elements is the topic of Lecture 041.


8. Visiting Every Index with a for Loop

When you need the position as well as the value, use the counting loop from Lecture 026 with i < list.length:

dart
void main() {
  var names = ['Ali', 'Sara', 'Zayan'];
  for (var i = 0; i < names.length; i++) {
    print('${i + 1}. ${names[i]}');
  }
}
output
1. Ali
2. Sara
3. Zayan

People count from 1, so we print i + 1 but read names[i]. A counting loop can also change elements, which a for-in loop cannot:

dart
void main() {
  var prices = [100, 250, 400];
  for (var i = 0; i < prices.length; i++) {
    prices[i] = prices[i] * 2;
  }
  print(prices);
}
output
[200, 500, 800]

9. Finding a Position with indexOf

The reverse question — "at which index is this value?" — is answered by indexOf, just as for strings in Lecture 008:

dart
void main() {
  var names = ['Ali', 'Sara', 'Zayan', 'Sara'];
  print(names.indexOf('Sara'));
  print(names.indexOf('Omar'));
}
output
1
-1

It returns the first match, or -1 when the value isn't there. Always check for -1 before using the result as an index. Searching a list properly is the topic of Lecture 042.


10. Nullable Elements vs a Nullable List

Where you put the ? matters:

  • List<int?> — the list always exists, but an element may be null.
  • List<int>? — the elements are never null, but the whole list may be missing.
dart
List<int>? savedMarks;

void main() {
  List<int?> scores = [85, null, 78];
  print(scores[1] ?? 0);

  print(savedMarks?[0]);
  print(savedMarks?.length ?? 0);
}
output
0
null
0

Reading from List<int?> gives an int?, so ?? supplies a default. On a List<int>?, ?[] (Lecture 014) reads only if the list exists — savedMarks was never given one, so it is still null. Writing savedMarks[0] is an error:

output
Error: Operator '[]' cannot be called on 'List<int>?' because it is potentially null.

11. A Real-World Example

dart
void main() {
  var students = ['Ali', 'Sara', 'Zayan'];
  var marks = [72, 88, 64];

  marks[2] = 69; // Zayan's paper was rechecked

  for (var i = 0; i < students.length; i++) {
    print('${students[i]}: ${marks[i]}');
  }

  var top = marks.indexOf(88);
  print('Top student: ${students[top]}');
  print('First: ${students.first}, last: ${students.last}');
}
output
Ali: 72
Sara: 88
Zayan: 69
Top student: Sara
First: Ali, last: Zayan

Two lists line up by index: students[i] and marks[i] describe the same person. The counting loop gives us i for both, and indexOf turns a mark back into a position.


Code Examples

Example 1 — Reading by Index

dart
void main() {
  var cities = ['Lahore', 'Karachi', 'Islamabad'];
  print(cities[0]);
  print(cities[2]);
}
output
Lahore
Islamabad

Example 2 — first, last, and length - 1

dart
void main() {
  var ages = [6, 18, 20, 35];
  print(ages.first);
  print(ages.last);
  print(ages[ages.length - 1]);
}
output
6
35
35

Example 3 — Replacing an Element

dart
void main() {
  var names = ['Ali', 'Sara', 'Zayan'];
  names[0] = 'Omar';
  print(names);
}
output
[Omar, Sara, Zayan]

Example 4 — An Index from a Variable

dart
void main() {
  var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
  var today = 3;
  print('Today: ${days[today]}');
  print('Tomorrow: ${days[today + 1]}');
}
output
Today: Thu
Tomorrow: Fri

Example 5 — Printing Index and Value

dart
void main() {
  var colors = ['red', 'green', 'blue'];
  for (var i = 0; i < colors.length; i++) {
    print('$i -> ${colors[i]}');
  }
}
output
0 -> red
1 -> green
2 -> blue

Example 6 — indexOf

dart
void main() {
  var scores = [40, 75, 90, 75];
  print(scores.indexOf(75));
  print(scores.indexOf(100));
}
output
1
-1

Example 7 — Student Marks

dart
void main() {
  var marks = [80, 75, 85, 90];
  marks[1] += 5;
  var total = 0;
  for (var i = 0; i < marks.length; i++) {
    total += marks[i];
  }
  print('Marks: $marks');
  print('Total: $total');
}
output
Marks: [80, 80, 85, 90]
Total: 335

How it works

  1. marks[1] += 5 turns the second mark 75 into 80.
  2. The loop reads marks[0] to marks[3] and adds each to total.

Example 8 — Shopping Total

dart
void main() {
  var items = ['Notebook', 'Pen', 'Bag'];
  var prices = [500, 50, 1500];
  var quantities = [3, 4, 1];
  var total = 0;
  for (var i = 0; i < items.length; i++) {
    var cost = prices[i] * quantities[i];
    print('${items[i]}: $cost');
    total += cost;
  }
  print('Total: $total');
}
output
Notebook: 1500
Pen: 200
Bag: 1500
Total: 3200

How it works

  1. Three lists line up by index: item i has price i and quantity i.
  2. One counting loop reads all three with the same i.

Example 9 — Bank Balance History

dart
void main() {
  var balances = [1000.0, 1250.5, 1150.5];
  print('Opening: ${balances.first}');
  print('Current: ${balances.last}');
  print('Change: ${balances.last - balances.first}');
}
output
Opening: 1000.0
Current: 1150.5
Change: 150.5

Example 10 — Temperature Conversion in Place

dart
void main() {
  var temperatures = [20.0, 25.0, 30.0];
  for (var i = 0; i < temperatures.length; i++) {
    temperatures[i] = temperatures[i] * 9 / 5 + 32;
  }
  print(temperatures);
}
output
[68.0, 77.0, 86.0]

How it works

  1. Each pass reads the Celsius value at index i and stores the Fahrenheit value back in the same position.
  2. A for-in loop could not do this — assigning to its loop variable doesn't touch the list.

Common Beginner Mistakes

1. Treating the first element as index 1

dart
void main() {
  var names = ['Ali', 'Sara', 'Zayan'];
  print(names[1]); // ✗ wanted Ali
}
output
Sara

No error — just the wrong person. The first element is names[0].

2. Using length as an index

dart
void main() {
  var marks = [85, 92, 78];
  // print(marks[marks.length]); // ✗ one past the end
}
output
Unhandled exception:
RangeError (length): Invalid value: Not in inclusive range 0..2: 3

The last index is length - 1, or simply use last.

3. Writing <= in the loop condition

dart
void main() {
  var marks = [85, 92, 78];
  // for (var i = 0; i <= marks.length; i++) { // ✗ should be <
  //   print(marks[i]);
  // }
}
output
85
92
78
Unhandled exception:
RangeError (length): Invalid value: Not in inclusive range 0..2: 3

4. Trying to add with an index

dart
void main() {
  var marks = [85, 92, 78];
  // marks[3] = 60; // ✗ there is no index 3 yet
}
output
Unhandled exception:
RangeError (index): Invalid value: Not in inclusive range 0..2: 3

Assigning by index only replaces. Adding comes in Lecture 041.

5. Calling first on an empty list

dart
void main() {
  var marks = <int>[];
  // print(marks.first); // ✗ there is no first element
}
output
Unhandled exception:
Bad state: No element

Check isEmpty (Lecture 039) before reading first or last.

6. Using indexOf's result without checking for -1

dart
void main() {
  var names = ['Ali', 'Sara'];
  var position = names.indexOf('Omar');
  // print(names[position]); // ✗ position is -1
}
output
Unhandled exception:
RangeError (length): Invalid value: Not in inclusive range 0..1: -1

7. Using a nullable element as a plain value

dart
void main() {
  List<int?> scores = [85, null, 78];
  // int first = scores[0]; // ✗
}
output
Error: A value of type 'int?' can't be assigned to a variable of type 'int'.

Supply a default: int first = scores[0] ?? 0;.


Best Practices

  • Remember that indexes start at 0 and end at length - 1.
  • Prefer first and last over [0] and [length - 1] — but only on a non-empty list.
  • Write loop conditions as i < list.length, never <= and never a fixed number.
  • Use for-in when you only need values; use a counting loop when you need positions or want to change elements.
  • Check indexOf for -1 before using its result.
  • Put the ? where the null can really appear: List<int?> or List<int>?.

Mini Challenge

Sara's weekly temperatures are [22, 24, 19, 27, 25]. The third reading was entered wrongly and should be 21. Fix it, then print every day as Day N: T and finally the first and last readings.

Your program should print exactly:

output
Day 1: 22
Day 2: 24
Day 3: 21
Day 4: 27
Day 5: 25
First: 22, last: 25

Try it yourself before opening the solution.

Show solution
dart
void main() {
  var temperatures = [22, 24, 19, 27, 25];
  temperatures[2] = 21;
  for (var i = 0; i < temperatures.length; i++) {
    print('Day ${i + 1}: ${temperatures[i]}');
  }
  print('First: ${temperatures.first}, last: ${temperatures.last}');
}
output
Day 1: 22
Day 2: 24
Day 3: 21
Day 4: 27
Day 5: 25
First: 22, last: 25

How it works

  1. The third reading is at index 2, so temperatures[2] = 21 fixes it.
  2. The loop prints i + 1 as the day number and temperatures[i] as the value.

Practice Questions

Work through these in order — they run from beginner to application to challenge. Every question gives you exact values, so you can compare your output with the answers.

Beginner

  1. Create var fruits = ['apple', 'banana', 'cherry']; and print the second fruit.
  2. For the same list, print the last fruit three ways: with last, with length - 1, and with a fixed index.
  3. Create var marks = [60, 70, 80];, change the first mark to 65, and print the list.

Application

  1. Print every element of ['Ali', 'Sara', 'Zayan'] as Student 1: Ali and so on.

  2. Given var prices = [100, 200, 300];, add 50 to every price with a counting loop and print the list.

  3. Given var names = ['Ali', 'Sara', 'Zayan'];, print the index of 'Zayan' and of 'Omar'.

  4. This program crashes. Explain why in one sentence, then fix it:

    dart
    void main() {
      var ages = [6, 18, 20];
      print(ages[3]);
    }
  5. Create List<int?> scores = [50, null, 90]; and print the sum of all scores, counting null as 0.

Challenge

  1. Swap the first and last elements of var names = ['Ali', 'Sara', 'Zayan']; and print the list. (Hint: you need a temporary variable.)
  2. Two lists line up by index: var products = ['Pen', 'Bag', 'Cap']; and var stock = [12, 0, 5];. Look up 'Bag' with indexOf and print Bag: 0 in stock. Then do the same for 'Hat', printing Hat: not sold here when it isn't found.

Practice Answers

Question 1 — Solution

dart
void main() {
  var fruits = ['apple', 'banana', 'cherry'];
  print(fruits[1]);
}
output
banana

Question 2 — Solution

dart
void main() {
  var fruits = ['apple', 'banana', 'cherry'];
  print(fruits.last);
  print(fruits[fruits.length - 1]);
  print(fruits[2]);
}
output
cherry
cherry
cherry

Question 3 — Solution

dart
void main() {
  var marks = [60, 70, 80];
  marks[0] = 65;
  print(marks);
}
output
[65, 70, 80]

Question 4 — Solution

dart
void main() {
  var students = ['Ali', 'Sara', 'Zayan'];
  for (var i = 0; i < students.length; i++) {
    print('Student ${i + 1}: ${students[i]}');
  }
}
output
Student 1: Ali
Student 2: Sara
Student 3: Zayan

Question 5 — Solution

dart
void main() {
  var prices = [100, 200, 300];
  for (var i = 0; i < prices.length; i++) {
    prices[i] += 50;
  }
  print(prices);
}
output
[150, 250, 350]

Question 6 — Solution

dart
void main() {
  var names = ['Ali', 'Sara', 'Zayan'];
  print(names.indexOf('Zayan'));
  print(names.indexOf('Omar'));
}
output
2
-1

Question 7 — Solution

The list has 3 elements, so its indexes are 0..2 and ages[3] throws a RangeError.

dart
void main() {
  var ages = [6, 18, 20];
  print(ages[2]);
}
output
20

print(ages.last); works too.

Question 8 — Solution

dart
void main() {
  List<int?> scores = [50, null, 90];
  var total = 0;
  for (var i = 0; i < scores.length; i++) {
    total += scores[i] ?? 0;
  }
  print(total);
}
output
140

Question 9 — Solution

dart
void main() {
  var names = ['Ali', 'Sara', 'Zayan'];
  var temp = names[0];
  names[0] = names[names.length - 1];
  names[names.length - 1] = temp;
  print(names);
}
output
[Zayan, Sara, Ali]

Without temp, the first assignment would overwrite 'Ali' before it could be moved.

Question 10 — Solution

dart
void main() {
  var products = ['Pen', 'Bag', 'Cap'];
  var stock = [12, 0, 5];

  var bag = products.indexOf('Bag');
  if (bag != -1) {
    print('Bag: ${stock[bag]} in stock');
  }

  var hat = products.indexOf('Hat');
  if (hat == -1) {
    print('Hat: not sold here');
  } else {
    print('Hat: ${stock[hat]} in stock');
  }
}
output
Bag: 0 in stock
Hat: not sold here

Quick Revision

  1. What is the index of the first element of a list?
  2. What is the last valid index of a list with 5 elements?
  3. What do first and last return? What happens on an empty list?
  4. How do you replace the element at index 2?
  5. What does RangeError ... Not in inclusive range 0..2: 3 tell you?
  6. When do you need a counting for loop instead of for-in?
  7. What does indexOf return when the value is missing?
  8. What is the difference between List<int?> and List<int>??

Key Takeaways

  • Every element has an index; counting starts at 0 and ends at length - 1.
  • list[i] reads an element; list[i] = value replaces it, checked against the element type.
  • first and last read the ends; on an empty list they throw Bad state: No element.
  • A missing index compiles but crashes with a RangeError — both for reading and assigning.
  • Loop over positions with for (var i = 0; i < list.length; i++); it can change elements.
  • indexOf returns the first matching index, or -1.
  • List<int?> may hold null elements; List<int>? may itself be null.

What's Next?

Lecture 041 — Adding & Removing Elements. Every list in this lecture kept its size: we could read and replace, but marks[3] = 60 crashed. Real lists grow and shrink — a new student joins, an item leaves the cart. Next we will add and remove elements and watch length change as we do.


Video lecture

Subscribe
Placeholder video — the real recording isn't linked yet.