First, it looks like you want a new version of the iterator at each level of the nesting, and not just a single clone for the second and third level at the top, right? So the first step would be creating a new iterator inside each flat_map
. iter_a
is consumed by then, so we can't clone it; let's just make the same iterator anew.
itera
.flat_map(|(i, u)| {
let iterb = nums.iter().copied().enumerate();
iterb
.filter(move |(j, ..)| j != &i)
.flat_map(move |(j, v)| {
let iterc = nums.iter().copied().enumerate();
iterc
.filter(move |&(k, w)| j != k && k != i && u + v + w == 0)
.map(|(.., w)| vec![u, v, w])
})
})
.collect()
But Rust still doesn't like this because you're move
-ing nums
everywhere now. You can dodge this one by only moving a reference to nums
instead, because shared references implement Copy
.
fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
let nums = &nums;
// ...
Then I still get a
error[E0373]: closure may outlive the current function, but it borrows `v`, which is owned by the current function
But everything we're working with at this point should be Copy
(shared references or i32
), so I just slap one more move
on the guilty closure (the last closure in the function).
Here's the end result.
Incidentally, at this point it's clear that since you're only iterating things out and copying, you never really needed to consume the Vec
(nums
), and you could change the signature to
fn three_sum(nums: &[i32]) -> Vec<Vec<i32>> {
// And no more need for `let nums = &nums` as it's already a shared ref.
Basically this is a messy exercise of working around move
closures being everything-or-nothing. The workaround was making the "everything" case work by making everything Copy
, since you didn't need anything more than a shared reference to nums
anyway.
Edit: Alternatively, use for
loops to avoid so many nested closures.