Rust Trick
Table of Contents
1. Rust Trick
1.1. closure: borrowed value doesn't live long enough
use std::collections::HashMap; struct Solution {} impl Solution { pub fn number_of_boomerangs(points: Vec<Vec<i32>>) -> i32 { let n = points.len(); let mut distance = vec![HashMap::new(); n]; for i in 0..n { for j in i + 1..n { let (p1, p2) = (&points[i], &points[j]); let d = (p1[0] - p2[0]).pow(2) + (p1[1] - p2[1]).pow(2); *distance[i].entry(d).or_insert(0) += 1; *distance[j].entry(d).or_insert(0) += 1; } } // `m` does not live long enough. distance .into_iter() .flat_map(|m| m.values().map(|k| k * (k - 1))) .sum() } } fn main() { println!( "{:?}", Solution::number_of_boomerangs(vec![ vec![0, 0], vec![1, 0], vec![-1, 0], vec![0, 1], vec![0, -1], ]) ); }
1.1.1. 分析
只需考虑 closure 本身: |m| m.values().xxx
这里的 m 是一个值而不是引用, 所以它在 lifetime 为 closure 本身.但 m.values() 会返回一个 iter, 这个 iter 持有对 m 的引用.
因为 HashMap::values() 原型为 pub fn values(&self) -> Values<K, V>. 所以 closure 会返回 m 的引用, 导致出错.
简化的累似的问题为:
fn main() { let v = vec![1, 2, 3]; v.into_iter().map(|x| &x); }
1.1.2. 解决
// into_iter() 修改为 iter(), 使得 m 变为引用, 有更长的作用域 distance .iter() .flat_map(|m| m.values().map(|k| k * (k - 1))) .sum() // 不要返回引用: m.values().xxx distance .into_iter() .flat_map(|m| m.values().map(|k| k * (k - 1)).collect::<i32>()) .sum()