我有以下内容:
enum SomeType { VariantA(String), VariantB(String, i32), } fn transform(x: SomeType) -> SomeType { // very complicated transformation, reusing parts of x in order to produce result: match x { SomeType::VariantA(s) => SomeType::VariantB(s, 0), SomeType::VariantB(s, i) => SomeType::VariantB(s, 2 * i), } } fn main() { let mut data = vec![ SomeType::VariantA("hello".to_string()), SomeType::VariantA("bye".to_string()), SomeType::VariantB("asdf".to_string(), 34), ]; }
我现在想调用transform
每个元素data
并将结果值存回data
.现在,我当然可以做类似的事情,data.into_iter().map(transform).collect()
但这将分配一个新的Vec
.有没有办法在就地执行此操作,重用已分配的内存data
?有一次Vec::map_in_place
在Rust,但它已被删除了一段时间(我认为在1.4左右).
作为解决方法,我目前添加Dummy
-variant SomeType
,然后执行以下操作:
for x in &mut data { let original = ::std::mem::replace(x, SomeType::Dummy); *x = transform(original); }
但这感觉不对,而且,我必须处理SomeType::Dummy
代码中的其他地方,尽管它应该永远不会在这个循环之外可见.有没有更好的方法呢?
你的第一个问题不是map
,它是transform
.
transform
取得其论点的所有权,同时Vec
拥有其论据.任何一个人都必须给予,并且在这个问题上挖一个洞Vec
会是一个坏主意:如果transform
恐慌怎么办?
因此,最好的解决方法是将签名更改transform
为:
fn transform(x: &mut SomeType) { ... }
那么你可以这样做:
for x in &mut data { transform(x) }
其他解决方案将是笨重的,因为他们将需要处理transform
可能恐慌的事实.