supinf
supinf

Reputation: 302

What is the right way to have multiple linked lists and move data between them in Rust?

What is the right way to have multiple std::collections::LinkedLists where the number of those lists is unknown at compile time?

I'm filling them with data as well as merging them (e.g. using append()). I thought it would be good to have a vector that contains those lists, or contains references to those lists.

I have tried the following:

use std::collections::LinkedList;

fn listtest() {
    let mut v: Vec<LinkedList<i32>> = Vec::new();
    v.push(LinkedList::new()); // first list
    v.push(LinkedList::new()); // second list
    v[0].push_back(1); // fill with data
    v[1].push_back(3); // fill with data
    v[0].append(&mut v[1]); // merge lists
}

fn main() {
    listtest();
}

This fails to compile because I have two mutable references of v when using append(). I also tried using Vec<&mut LinkedList<i32>>, but did not succeed.

What would be the right approach to this problem?

Upvotes: 2

Views: 451

Answers (2)

Francis Gagn&#233;
Francis Gagn&#233;

Reputation: 65927

Most collections have an iter_mut method that returns an iterator that yields mutable references to each item in the collection. And these references can all be used at the same time! (But the references must come from the same iterator; you can't use references coming from separate calls to iter_mut concurrently.)

use std::collections::LinkedList;

fn listtest() {
    let mut v: Vec<LinkedList<i32>> = Vec::new();
    v.push(LinkedList::new()); // first list
    v.push(LinkedList::new()); // second list
    v[0].push_back(1); // fill with data
    v[1].push_back(3); // fill with data
    let mut vi = v.iter_mut();
    let first = vi.next().unwrap();
    let second = vi.next().unwrap();
    first.append(second); // merge lists
}

fn main() {
    listtest();
}

Also remember that iterators have the nth method for doing the equivalent of next in a loop.

Upvotes: 2

Shepmaster
Shepmaster

Reputation: 432059

There is no right approach. One possibility is to use split_at_mut. This creates two separate slices, each of which can be mutated separately from the other:

use std::collections::LinkedList;

fn main() {
    let mut v = vec![LinkedList::new(), LinkedList::new()];
    v[0].push_back(1);
    v[1].push_back(3);

    {
        let (head, tail) = v.split_at_mut(1);
        head[0].append(&mut tail[0]);
    }

    println!("{:?}", v);
}

See:

Upvotes: 5

Related Questions