我怎样才能把Vec<u64>
变成Vec<(&str, u64)>
,这样 前者的索引嵌入到后者的str
部分?
例如,[4, 9, 3]
应该变成[("0", 4), ("1", 9), ("2", 3)]
。
我想这样做的原因是因为我想绘制我的 矢量使用 TUI 中的条形图,这需要这样的类型。
我已经尝试了一些明显的事情,例如循环和推送:
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[E0716]: temporary value dropped while borrowed
--> src/main.rs:5:23
|
5 | result.push((&k.to_string(), *v));
| ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
...
8 | assert_eq!(result, [("0", 4), ("1", 9), ("2", 3)]);
| --------------------------------------------------- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
或使用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)>`
但无论我做什么,我似乎都无法绕过终身问题, 因为k.to_string()
活得不够长。
当然,如果有更好的方法来获取向量,我愿意接受建议 以其索引作为标签绘制。
你不能直接这样做,&str
借用字符串,这样字符串在你借用它们时必须保持活动状态,一般的答案是创建你的字符串,储存它们并借用它们,例如:
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)]);
}
虽然这将适用于您的具体情况data()
但很奇怪。如果不挖掘更多,很难判断是否有问题。在您链接的示例中,str
是静态的,可能它只是(或主要(打算像示例一样使用,因此您不需要将其与动态索引一起使用。
&str
引用必须指向比result
寿命更长的字符串。不能使用对临时字符串的引用,因为它们会过早删除。
一种选择是将所有String
存储在一个比result
寿命更长的集合中。预先计算它们,然后存储对这些长期字符串的引用:
let my_vec: Vec<u64> = vec![4, 3, 9];
let labels: Vec<String> = (0..my_vec.len())
.map(|i| i.to_string())
.collect();
let result: Vec<_> = labels.iter()
.zip(my_vec)
.map(|(k, v)| (k.as_str(), v))
.collect();
(游乐场(
这可能只会将您的问题提升一个级别。您可能没有一个好地方来存放String
,以便它们活得足够长。如果您希望它们在当前函数调用之后存活,则它们不能位于堆栈上的局部变量中。
第二种选择是将String
s转换为Box<str>
,然后用Box::leak
泄漏内存。泄露的参考文献永远存在,因此可以被视为'static
。
注意不要滥用这种技术,只是为了让编译器在抱怨生命周期时关闭它。只有当字符串永远存在确实有意义时,您才应该这样做。如果标签将在应用程序运行的整个过程中显示,则没关系。如果它们位于已关闭或以其他方式消失的 UI 元素中,请不要这样做。
let my_vec: Vec<u64> = vec![4, 3, 9];
let result: Vec<(&str, u64)> = my_vec.iter()
.enumerate()
.map(|(k, v)| (Box::leak(k.to_string().into_boxed_str()) as &str, *v))
.collect();
(游乐场(