What insert and remove do
push adds an item at the end of a Vec and pop takes the last one away. For any other position, use insert and remove.
insert(i, x) puts x at index i. The items from index i onward each move one place to the right to make room.
remove(i) takes out the item at index i and returns it. The items after it move one place to the left to close the gap.
let mut pets = vec!["Rex", "Milo"];
pets.insert(0, "Luna");
// pets is now ["Luna", "Rex", "Milo"]
let first = pets.remove(0);
// first is "Luna", and pets is now ["Rex", "Milo"]
Both methods change the vector, so it must be declared with let mut. Without mut, the compiler stops with "cannot borrow pets as mutable, as it is not declared as mutable".
Indexes move
After an insert or a removal, every item behind that spot has a new index. Starting from ["a", "b", "c", "d"], calling remove(1) leaves ["a", "c", "d"], and now "c" sits at index 1, not 2. If you need an index after changing the vector, work it out again.
Indexes past the end
An index that is too large makes the program panic. With a vector of length 3, remove(3) stops with "removal index (is 3) should be < len (is 3)", because there is no item at index 3. insert(5, x) stops with "insertion index (is 5) should be <= len (is 3)".
The one exception is that insert accepts the length itself: pets.insert(pets.len(), "Luna") adds at the end, just like push.
Inserting in the middle and at the end
Starting from [10, 20, 30], insert(1, 15) gives [10, 15, 20, 30], and remove(1) then returns 15 and leaves [10, 20, 30] again. Inserting at the length adds at the end: with ["Rex", "Milo", "Luna"], insert(line.len(), "Zed") gives ["Rex", "Milo", "Luna", "Zed"]. Inserting at index 0 puts the new item first.
Shifting is not free: every item behind the spot has to move. For a short list that doesn't matter, and it is the price of keeping the items in order.
The task, step by step
The vector starts as ["Rex", "Milo", "Luna"]. Bella goes second in line, which is index 1, so the first step is pets.insert(1, "Bella"). Milo and Luna each move one place to the right, and the length is now 4.
Next, Milo goes home. Because Bella came in, Milo has moved from index 1 to index 2, so the second step is pets.remove(2). The returned value is not needed, so it is simply ignored.
let mut pets = vec!["Rex", "Milo", "Luna"];
pets.insert(1, "Bella");
println!("{}", pets.len());
pets.remove(2);
println!("{} {} {}", pets[0], pets[1], pets[2]);
It prints:
4
Rex Bella Luna
Why the order of the two steps matters
The task does the insert first and the removal second, and the index of Milo depends on that order. Before Bella arrives, Milo is at index 1. After the insert, Bella is at index 1, Milo has moved to index 2, and Luna to index 3. Whenever you change a vector in several steps, say aloud what the vector looks like after each one, and read the next index from that picture.
Common mistakes
- Removing Milo with
remove(1). That index was right before the insert; after it, index 1 holds Bella. - Writing the arguments the wrong way round. The index comes first and the value second:
insert(1, "Bella"). - Forgetting
muton the vector.
Key takeaways
insert(i, x)adds at indexiand shifts later items right.remove(i)deletes indexi, returns the item, and shifts later items left.- Both need a
mutvector and panic on a bad index (exceptinsertat the length).
