如何将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()的寿命不够长。
当然,如果有更好的方法用它的索引作为标签来绘制向量,我会给出一些建议。
发布于 2020-05-23 22:25:13
您不能直接这样做,&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是静态的--可能它只是(或者主要)打算像示例那样使用,因此您不需要在动态索引中使用它。
发布于 2020-05-23 22:34:39
&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转换为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();(游乐场)
https://stackoverflow.com/questions/61979023
复制相似问题