将Vec <u64>转换为Vec <(&str,u64)>以获得tui :: BarChart数据

How can I turn a Vec<u64> into a Vec<(&str, u64)>, such that the index of the former is embedded into the str part of the latter?

For example, [4, 9, 3] should be turned into [("0", 4), ("1", 9), ("2", 3)].

The reason I want to do this is because I want to plot a barchart of my vector using the barchart from TUI, which requires a type like that.

我已经尝试了一些显而易见的事情,例如循环和推送:

fn main() {
    let my_vec: Vec<u64> = vec![4, 9, 3];
    let mut result: Vec<(&str, u64)> = Vec::new();
    for (k, v) in my_vec.iter().enumerate() {
        result.push((&k.to_string(), v));
    }

    assert_eq!(result, [("0", 4), ("1", 9), ("2", 3)]);
}
error[E0308]: mismatched types
 --> src/main.rs:5:38
  |
5 |         result.push((&k.to_string(), v));
  |                                      ^
  |                                      |
  |                                      expected `u64`, found `&u64`
  |                                      help: consider dereferencing the borrow: `*v`

or using map:

fn main() {
    let my_vec: Vec<u64> = vec![4, 9, 3];
    let result: Vec<(&str, u64)> = my_vec
        .into_iter()
        .enumerate()
        .map(|(k, v)| (&k.to_string(), v))
        .collect();

    assert_eq!(result, [("0", 4), ("1", 9), ("2", 3)]);
}
error[E0277]: a value of type `std::vec::Vec<(&str, u64)>` cannot be built from an iterator over elements of type `(&std::string::String, u64)`
 --> src/main.rs:7:10
  |
7 |         .collect();
  |          ^^^^^^^ value of type `std::vec::Vec<(&str, u64)>` cannot be built from `std::iter::Iterator<Item=(&std::string::String, u64)>`
  |
  = help: the trait `std::iter::FromIterator<(&std::string::String, u64)>` is not implemented for `std::vec::Vec<(&str, u64)>`

But whatever I do I just can't seem to get around the lifetime issue, as k.to_string() doesn't live long enough.

当然,如果有更好的方法来获取向量,我愿意提出建议 以其索引作为标签进行绘制。

评论
  • afuga
    afuga 回复

    You can't do it directly, &str borrow the string so the string must stay alive while you borrow them, the general answer is to create your string, stock them and borrow them, like for example:

    fn main() {
        let my_vec: Vec<u64> = vec![4, 9, 3];
    
        let my_owned : Vec<(String, u64)> = my_vec
            .into_iter()
            .enumerate()
            .map(|(k, v)| (k.to_string(), v))
            .collect();
    
        let result: Vec<(&str, u64)> = my_owned
            .iter()
            .map(|(k, v)| (k.as_str(), *v))
            .collect();
    
        assert_eq!(result, [("0", 4), ("1", 9), ("2", 3)]);
    }
    

    While this will work on your specific case data() is strange. Without digging more it's hard to tell if there is something wrong. In the example, you linked the str are static maybe it's only(or mainly) intended to be use like the example, and so you are not expected to use it with dynamic index.