使用flat_map将Vec <u8>转换为Vec <char>

时间:2017-12-14 21:30:22

标签: rust borrow-checker

我遇到了与Borrow-check error with variable not living long enough in nested lambda相似的情况,但我无法弄清楚我的情况有何不同:

let mut vec = vec![vec![0u8, 1u8], vec![2u8, 3u8], vec![4u8, 5u8]];
vec.iter().map(|row| {
    row.iter()
        .map(|d| format!("{:04b}", d))
        .flat_map(|s| s.chars())
        .collect::<Vec<_>>()
});

出现错误:

error[E0597]: `s` does not live long enough
 --> src/main.rs:6:35
  |
6 |             .flat_map(|s| s.chars())
  |                           -       ^ `s` dropped here while still borrowed
  |                           |
  |                           borrow occurs here
7 |             .collect::<Vec<_>>()
  |                                - borrowed value needs to live until here

我通过创建一个新的Vec并附加来解决这个问题,但我不清楚为什么第一种方法不起作用。

let mut tmp = vec![];
vec.iter()
    .map(|d| format!("{:04b}", d))
    .for_each(|s| {tmp.append(&mut s.chars().collect::<Vec<_>>());});

1 个答案:

答案 0 :(得分:2)

首先将闭包|d| format!("{:04b}", d)映射到迭代器上,产生String s,它们拥有自己的数据,因此可以完美地找到它。下一步中的flat_map()会在每个.chars()上调用String。这会隐式地将String解除为&str,并创建引用此借用的Chars迭代器。但现在我们遇到了一个问题 - 没有人拥有我们借用的String

一种解决方法是存储String s的临时向量:

let mut vec = vec![vec![0u8, 1u8], vec![2u8, 3u8], vec![4u8, 5u8]];
vec.iter().map(|row| {
    let strings: Vec<_> = row
        .iter()
        .map(|d| format!("{:04b}", d))
        .collect();
    strings
        .iter()
        .flat_map(|s| s.chars())
        .collect::<Vec<_>>()
});

现在我们有一个中间人String的所有者,一切正常。