Parsing vectors into a vector of tuples

Playground here:

I need to convert the following example into an array of tuples. The tuples will contain:

  • The entire vec
  • The first n characters of the vec (in this case, the first two only)

The tuples need to be in an array that goes left to right (first column from all, then second, etc)

   let vec1 = vec![vec![1, 1,2,2], vec![3, 3,4,4]];
   let vec2 = vec![vec![5, 5,6,6], vec![7, 7,8,8]];
   let all = vec![vec1, vec2];
    
    // expected result 
    let result = [ 
        [
            ([1,1,2,2], [1,1]),
            ([5,5,6,6], [5,5])
        ],
         [
            ([3,3,4,4], [3,3]),
            ([7,7,8,8], [7,7])
        ],
    ];

Sorry, for some reason vectors really confuse me in Rust! Any help is appreciated!

This sounds like some homework..

Anyway. I recommend you to read about iterators in Rust and the zip method in Iterator: Iterator in std::iter - Rust.

It's not homework. It's for an actual use case in software. I realize it seems like busywork but this seemed like the best way to show a contrived example.

Can you at least share your thoughts around the problem at hand or any code that you have tried so far and for some reason fails to achieve the task in question?

Sure. I've cleaned up the playground because it was giving me lots of compiler errors. I need to start a result vec that holds the vec of tuples. Instantiating this is tough because it keeps complaining about conversions between usizes, i32s, and u8s (which this is actually dealing with)

So I need to loop though each column and then each row to extract the value of the column and the first two items in the vec as a tuple.

The main issue for me has been coercing the types to make the compiler happy.

Is the length of all source vectors always 4? Should the result arrays' length be 4 and 2, always?

No, this is actually for parsing the contents of a binary file, so the array lengths will be variable, but the "chunk size" will always be 16 (even though I'm using 2 in this example)

EDIT: in fact, the number of "files" to parse is also variable. In this example I have two rows, but there could be 1...infinity rows to parse.

I'm not really following you here. What is a "file" and what is a "row" in your example?

Each file will produce a collection of Vec<u8>, so Vec<Vec<u8>>

There will be multiple files, so those I'm counting as "rows" I need to compare the vecs in each file to spot differences and process those. So in this case, I want a collection derived from each "file" and group them together. But in reality, the above example really does mimic the actual problem close enough to get me going.

Ok, this seems to work. Feels weird, but the values match up.

    let vec1 = vec![vec![1, 1,2,2], vec![3, 3,4,4]];
    let vec2 = vec![vec![5, 5,6,6], vec![7, 7,8,8]];
    let all = vec![vec1, vec2];
    let r  = &mut vec![];
    all[0].iter().enumerate().for_each(|(i, _column)| {
        let mut c = vec![];
        all.iter().enumerate().for_each(|(j, _item)| {
            let foo = &all[j][i];
            c.push((foo, &foo[0..2]));
        });
        r.push(c);
    });
    println!("r {:?}",r );
}

Playground here:

Any improvements?

Yes, you should likely make a copy here instead of keeping a reference.

            c.push((foo, [u8; 2]::from(&foo[0..2])));

Can you explain why? I thought that &foo[0..2] already creates a "slice" which is a view of that data. I don't need to copy that data, only use it as a lookup comparator.

Copying two u8 is trivial. Having to deal with lifetimes because you prefer references over copying 16 bits can be very annoying. Here's a version of your code solely relying on the Iterator interface, rather than indexing:

fn main() {
    let vec1 = vec![vec![1, 1, 2, 2], vec![3, 3, 4, 4]];
    let vec2 = vec![vec![5, 5, 6, 6], vec![7, 7, 8, 8]];
    let all: Vec<Vec<Vec<u8>>> = vec![vec1, vec2];

    let res: Vec<Vec<(Vec<u8>, [u8; 2])>> = all
        .into_iter()
        .map(|a| {
            a.into_iter()
                .map(|b| {
                    let first = [b[0], b[1]];
                    (b, first)
                })
                .collect()
        })
        .collect();

    println!("{res:#?}");
}

Playground.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.