I want to spit my vector into small vectors, but the item type cannot be cloned. Is there any way I can still split it?
For example:
struct Foo {}
fn main() {
let vector = vec![Foo {}; 10];
let vectors: Vec<Vec<Foo>> = vector
.chunks(2)
.map(|sub_foos| sub_foos.into_vec())
.collect();
}
H2CO3
February 23, 2023, 10:28am
2
let vectors: Vec<Vec<&Foo>> = vector
.chunks(2)
.map(|sub_foos| sub_foos.iter().collect())
.collect();
I do want to get a Vec<Vec<Foo>>
in this case.
If you can use nightly feature, then.
let vectors: Vec<Vec<Foo>> = vector
.into_iter()
.array_chunks::<2>()
.map(|sub_foos| sub_foos.into())
.collect();
If you cannot:
let mut temp = vec![];
let vectors: Vec<Vec<Foo>> = vector
.into_iter()
.filter_map(|foo| {
temp.push(foo);
(temp.len() == 2).then(|| std::mem::take(&mut temp))
})
.collect();
H2CO3
February 23, 2023, 10:42am
6
Then you can't use chunks()
because it gives you references. I don't think there's a stable, ready-made combinator for this in std
; you may want to watch out for array_chunks()
becoming stable. In the meantime, use a loop .
for (i, v) in vector.into_iter().enumerate() {
tmp.push(v);
if tmp.len() == 2 {
vectors.push(core::mem::take(&mut tmp));
}
}
if tmp.len() > 0 {
vectors.push(tmp);
}
jofas
February 23, 2023, 10:45am
7
Itertools offers a chunks
method:
use itertools::Itertools;
#[derive(PartialEq, Debug)]
struct Foo {}
fn main() {
let vector = vec![Foo {}, Foo {}, Foo {}, Foo {}];
let mut vectors: Vec<Vec<Foo>> = vec![];
for chunk in &vector.into_iter().chunks(2) {
vectors.push(chunk.collect());
}
assert_eq!(vectors, vec![vec![Foo {}, Foo {}], vec![Foo {}, Foo {}]]);
}
Playground.
Instead of a for loop you can also use this:
let vectors: Vec<Vec<Foo>> = vector
.into_iter()
.chunks(2)
.into_iter()
.map(|c| c.collect())
.collect();
1 Like
H2CO3
February 23, 2023, 10:50am
8
And the closure is unnecessary, too, you can just .map(Iterator::collect)
.
1 Like
Here's another way without using third party dependencies:
#[derive(Debug, PartialEq)] // Just for the assert
struct Foo {}
fn main() {
let vector = vec![Foo {}, Foo {}, Foo {}, Foo {}];
let chunk_size = 2;
let chunks = (vector.len() + chunk_size - 1) / chunk_size;
let mut iter = vector.into_iter();
let vectors: Vec<Vec<Foo>> = (0..chunks)
.map(|_| iter.by_ref().take(chunk_size).collect())
.collect();
assert_eq!(vectors, vec![vec![Foo {}, Foo {}], vec![Foo {}, Foo {}]]);
}
1 Like
It seems that this array_chunks
takes a constant, which I can't offer at compile time.
system
Closed
May 24, 2023, 12:11pm
11
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.