HagaiH
HagaiH

Reputation: 413

Reverse order of a reference to immutable array slice

I would like to reverse the order of a slice:

&[1, 2, 3] -> &[3, 2, 1]

This is my code:

fn iterate_over_file(data: &[u8], ...) -> ... {
    ...
    for cur_data in data.chunks(chunk_size) {
         let reversed_cur_data = cur_data.reverse() // this returns ()
         ...
    ...
 }

This data parameter comes from a file I read in using FileBuffer, and I'd like to keep it as a referenced slice (and not turn it into an owned Vec, since it's a heavy computation to make).

How could I reverse the order of cur_data with the minimal amount of operations and memory allocation? Its length is known for a specific runtime of my program (called here chunk_size), but it changes between different runs. reversed() seems to return (), which makes sense as it's done in-place, and I only have a referenced slice. .iter().rev() creates an iterator, but then I'd have to call .next() on it several times to get the slice back, which is both not elegant and not effective, as I have at least tens of millions of cur_data lines per file.

Upvotes: 9

Views: 11027

Answers (1)

user4815162342
user4815162342

Reputation: 154866

Not only does reverse return (), it also requires a mutable slice, which you do not have. The optimal solution depends on exactly what you need to do with the data. If you only need to iterate over the data, cur_data.iter().rev() is exactly the right and the most efficient choice.

If you need the reversed data inside a slice for further processing, such as to send the reversed chunk to a function that expects a slice, you can collect the data into a vector. To avoid a new allocation for each chunk, you can reuse the same vector across all loop iterations:

let mut reversed = Vec::with_capacity(chunk_size);
for cur_data in data.chunks(chunk_size) {
     // truncate the slice at the beginning of each iteration.
     // Vec explicitly guarantees that this will *not* deallocate,
     // it will only reset its internal length. An allocation will
     // thus only happen prior to the loop.
     reversed.truncate(0);
     reversed.extend(cur_data.iter().rev());
     // &reversed is now the reversed_cur_data you need
     ...
}

Upvotes: 15

Related Questions