Search code examples
vectorrustslicerust-itertools

Rust vector type conversion / interface issue between Itertools and function with slice indexing


Aim: generate permutations and index into each one in parallel.

Attempt: use Itertools to assign all permutations to a resulting vector and then use rayon to process each one.

Minimum reproducible code:

use rayon::iter::ParallelIterator;
use rayon::iter::IntoParallelIterator;
use itertools::Itertools;

fn main() {
    let data: Vec<u128> = [0, 1, 2, 3, 4, 5, 6].to_vec();
    let k = 4;

    let vector = data.into_iter().permutations(k).map_into::<Vec<u128>> 
    ().collect_vec();

    (vector).into_par_iter().for_each(move |x| index_vec(x));

}

fn index_vec(i: Vec<u128>) -> () {
    let mut colour_code: String = String::from("");
    let mut index_position = 0;

    for _ in 0..4 {
        colour_code.push_str(COLOURS[i[index_position]]);
        colour_code.push(' ');
        index_position += 1;
    }
    println!("Colour code: {}", colour_code);
}

const COLOURS: [&str; 7] = [
    "red", "yellow", "blue", "green", "pink", "grey", "orange",
];

Error: slice indices are of type usize or ranges of usize

However, if I change all vectors to type usize, then Itertools throws an error on the map_into method: the trait From<Vec<u128>> is not implemented for Vec<usize>.

How can I make Itertools and slice indices cooperate?


Solution

  • To make the posted code compile and run all you need to do is convert from the u128 to a usize, which is used for indexing the array.

    I would consider this "safe" currently, as there are no systems with pointer sizes > 128 bytes, that I know of. However beware, that this conversion can fail in theory

    So the fixed code would look like that:

    use rayon::iter::ParallelIterator;
    use rayon::iter::IntoParallelIterator;
    use itertools::Itertools;
    
    fn main() {
        let data: Vec<u128> = [0, 1, 2, 3, 4, 5, 6].to_vec();
        let k = 4;
    
        let vector = data.into_iter().permutations(k).map_into::<Vec<u128>> 
        ().collect_vec();
    
        (vector).into_par_iter().for_each(move |x| index_vec(x));
    
    }
    
    fn index_vec(i: Vec<u128>) -> () {
        let mut colour_code: String = String::from("");
        let mut index_position = 0;
    
        for _ in 0..4 {
            colour_code.push_str(COLOURS[i[index_position] as usize]);
            colour_code.push(' ');
            index_position += 1;
        }
        println!("Colour code: {}", colour_code);
    }
    
    const COLOURS: [&str; 7] = [
        "red", "yellow", "blue", "green", "pink", "grey", "orange",
    ];
    

    Playground link is here.