Jay Weng
Jay Weng

Reputation: 11

Rust copy vector from cycle?

I can copy a vector from a slice like so:

let mut my_vector = Vec::from_iter(other_vector[n..n+5].iter().cloned());

Is there a way to copy a vector so that I wrap around the end? e.g., for the vector [1,2,3,4,5] I could copy [5,1,2]

std::iter::Cycle provides a cycle iterator but I'm not sure how to take advantage of it.

Upvotes: 0

Views: 557

Answers (2)

Ratah
Ratah

Reputation: 302

With a functional programming approach, you can map through index iterator from 0 to 3 and then collect corresponding vector values (got using modulo concept).

fn main(){
let n = 4;
let other_vector = vec![1, 2, 3, 4, 5];
let modulo = other_vector.len();
let l = 3;
let my_vector: Vec<i32> = (0..l).into_iter().map(|i| other_vector[(n+i)%modulo]).collect();
dbg!(my_vector);

}

rust playground

I do a benchmark to compare the 2 methods std::iter::Cycle (@Prime_Aqasix response) and map/collect method

#![feature(test)]
extern crate test;

use test::Bencher;
use std::iter::FromIterator;

fn test1(other_vector:&Vec<i32>) {
    let n = 4;
    let my_vector = Vec::from_iter(other_vector.iter().cycle().skip(n).take(3).cloned());
    dbg!(my_vector);
}

fn test2(other_vector:&Vec<i32>) {
    let n = 4;
    let modulo = other_vector.len();
    let l = 3;
    let my_vector: Vec<i32> = (0..l).into_iter().map(|i| other_vector[(n+i)%modulo]).collect();
    dbg!(my_vector);
}

#[bench]
fn bench_test1(bencher: &mut Bencher) {

    let other_vector: Vec<i32> = (0..10000).map(|v| v + 1000).collect();
    bencher.iter(|| test1(&other_vector));
}

#[bench]
fn bench_test2(bencher: &mut Bencher) {

    let other_vector: Vec<i32> = (0..10000).map(|v| v + 1000).collect();
    bencher.iter(|| test2(&other_vector));
}

To execute, you just have to run "cargo bench" command. These are my results:

First test:

running 2 tests
test bench_test1 ... bench:         686 ns/iter (+/- 487)
test bench_test2 ... bench:         576 ns/iter (+/- 398)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 11.78s

Second test:

running 2 tests
test bench_test1 ... bench:         696 ns/iter (+/- 755)
test bench_test2 ... bench:         622 ns/iter (+/- 419)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 13.32s

Third test:

running 2 tests
test bench_test1 ... bench:         638 ns/iter (+/- 537)
test bench_test2 ... bench:         494 ns/iter (+/- 529)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out; finished in 4.76s

Functional programming approach is more likely speedup the copy. This is a good alternative to std::iter::cycle

Upvotes: 0

8176135
8176135

Reputation: 4133

You can use std::iter::Cycle directly after you converted it to an iterator, and then use skip to get to the place you want in the iterator, before using take to take the number of elements you want in the new iterator.

fn main() {
    let n = 4;
    let other_vector = vec![1,2,3,4,5];
    let my_vector = Vec::from_iter(other_vector.iter().cycle().skip(n).take(3).cloned());
    dbg!(my_vector);
}

Rust Playground

Upvotes: 0

Related Questions