如何在 Rust 中附加到散列 table 中的字符串值?
How to append to string values in a hash table in Rust?
我有一个源文件,其中包含给定日期的许多产品的文本 CSV 行。我想使用 Rust 整理这些文件,以便我最终得到许多新的目标 CSV 文件,每个产品一个,每个包含仅特定于该产品的部分行。
我目前的解决方案是遍历源文件的行并使用 HashMap<String, String>
来收集每个产品的行。我拆分每个源代码行并使用包含产品 ID 的元素作为键,在我的 HashMap
中获得一个 Entry
(占用或空置)。如果它是空的,我用预先分配给定容量的新 String
初始化该值,以便之后我可以有效地附加到它。
// so far, so good (the first CSV item is the product ID)
let mystringval = productmap.entry(splitsource[0].to_owned()).or_insert(String::with_capacity(SOME_CAPACITY));
然后我想将同一源代码行的格式化元素附加到此 Entry
。网上有很多例子,比如
https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.entry
如果 HashMap
值为整数,如何实现此功能:
// this works if you obtain an Entry from a HashMap containing int vals
*myval += 1;
我还没有想出如何使用这种语法将更多文本附加到我从 HashMap<String, String>
获得的 Entry
中,我已尽最大努力研究在线示例。令人惊讶的是,在 Rust 数据结构中操作非数字条目的例子很少。
// using the Entry obtained from my first code snippet above
*mystringval.push_str(sourcePortion.as_str());
尝试编译它会产生以下错误:
error: type `()` cannot be dereferenced
--> coll.rs:102:17
|
102 | *mystringval.push_str(sourcePortion.as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
如何在 Entry
值内追加 String
?
如果您检查 or_insert
返回的类型:
fn update_count(map: &mut HashMap<&str, u32>) {
let () = map.entry("hello").or_insert(0);
}
你会看到它是一个可变引用:
error[E0308]: mismatched types
--> src/main.rs:4:9
|
4 | let () = map.entry("hello").or_insert(0);
| ^^ expected &mut u32, found ()
|
= note: expected type `&mut u32`
found type `()`
这意味着您可以调用任何需要 &mut self
接收器的方法,而无需额外的语法:
fn update_mapping(map: &mut HashMap<&str, String>) {
map.entry("hello").or_insert_with(String::new).push_str("wow")
}
回到整数形式,如果我们不放解引用会怎样?
fn update_count(map: &mut HashMap<&str, i32>) {
map.entry("hello").or_insert(0) += 1;
}
error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut i32`
--> src/main.rs:4:5
|
4 | map.entry("hello").or_insert(0) += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use `+=` on type `&mut i32`
error[E0067]: invalid left-hand side expression
--> src/main.rs:4:5
|
4 | map.entry("hello").or_insert(0) += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid expression for left-hand side
不同之处在于 +=
运算符 自动 对表达式的左侧进行可变引用。展开后,它可能看起来像这样:
use std::ops::AddAssign;
fn update_count(map: &mut HashMap<&str, i32>) {
AddAssign::add_assign(&mut map.entry("hello").or_insert(0), 1);
}
添加显式取消引用会将类型恢复为已实现特征的类型:
use std::ops::AddAssign;
fn update_count(map: &mut HashMap<&str, i32>) {
AddAssign::add_assign(&mut (*map.entry("hello").or_insert(0)), 1);
}
*mystringval.push_str(sourcePortion.as_str());
被解析为 *(mystringval.push_str(sourcePortion.as_str()));
并且由于 String::push_str
returns ()
,您得到 () cannot be dereferenced
错误。
在取消引用周围使用括号解决了优先级问题:
(*mystringval).push_str(sourcePortion.as_str());
*myval += 1
起作用的原因是因为一元 *
的优先级高于 +=
,这意味着它被解析为
(*myval) += 1
因为 or_insert
returns &mut V
,你不需要在调用它的方法之前取消引用它。以下也适用:
mystringval.push_str(sourcePortion.as_str());
我有一个源文件,其中包含给定日期的许多产品的文本 CSV 行。我想使用 Rust 整理这些文件,以便我最终得到许多新的目标 CSV 文件,每个产品一个,每个包含仅特定于该产品的部分行。
我目前的解决方案是遍历源文件的行并使用 HashMap<String, String>
来收集每个产品的行。我拆分每个源代码行并使用包含产品 ID 的元素作为键,在我的 HashMap
中获得一个 Entry
(占用或空置)。如果它是空的,我用预先分配给定容量的新 String
初始化该值,以便之后我可以有效地附加到它。
// so far, so good (the first CSV item is the product ID)
let mystringval = productmap.entry(splitsource[0].to_owned()).or_insert(String::with_capacity(SOME_CAPACITY));
然后我想将同一源代码行的格式化元素附加到此 Entry
。网上有很多例子,比如
https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.entry
如果 HashMap
值为整数,如何实现此功能:
// this works if you obtain an Entry from a HashMap containing int vals
*myval += 1;
我还没有想出如何使用这种语法将更多文本附加到我从 HashMap<String, String>
获得的 Entry
中,我已尽最大努力研究在线示例。令人惊讶的是,在 Rust 数据结构中操作非数字条目的例子很少。
// using the Entry obtained from my first code snippet above
*mystringval.push_str(sourcePortion.as_str());
尝试编译它会产生以下错误:
error: type `()` cannot be dereferenced
--> coll.rs:102:17
|
102 | *mystringval.push_str(sourcePortion.as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
如何在 Entry
值内追加 String
?
如果您检查 or_insert
返回的类型:
fn update_count(map: &mut HashMap<&str, u32>) {
let () = map.entry("hello").or_insert(0);
}
你会看到它是一个可变引用:
error[E0308]: mismatched types
--> src/main.rs:4:9
|
4 | let () = map.entry("hello").or_insert(0);
| ^^ expected &mut u32, found ()
|
= note: expected type `&mut u32`
found type `()`
这意味着您可以调用任何需要 &mut self
接收器的方法,而无需额外的语法:
fn update_mapping(map: &mut HashMap<&str, String>) {
map.entry("hello").or_insert_with(String::new).push_str("wow")
}
回到整数形式,如果我们不放解引用会怎样?
fn update_count(map: &mut HashMap<&str, i32>) {
map.entry("hello").or_insert(0) += 1;
}
error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut i32`
--> src/main.rs:4:5
|
4 | map.entry("hello").or_insert(0) += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use `+=` on type `&mut i32`
error[E0067]: invalid left-hand side expression
--> src/main.rs:4:5
|
4 | map.entry("hello").or_insert(0) += 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid expression for left-hand side
不同之处在于 +=
运算符 自动 对表达式的左侧进行可变引用。展开后,它可能看起来像这样:
use std::ops::AddAssign;
fn update_count(map: &mut HashMap<&str, i32>) {
AddAssign::add_assign(&mut map.entry("hello").or_insert(0), 1);
}
添加显式取消引用会将类型恢复为已实现特征的类型:
use std::ops::AddAssign;
fn update_count(map: &mut HashMap<&str, i32>) {
AddAssign::add_assign(&mut (*map.entry("hello").or_insert(0)), 1);
}
*mystringval.push_str(sourcePortion.as_str());
被解析为 *(mystringval.push_str(sourcePortion.as_str()));
并且由于 String::push_str
returns ()
,您得到 () cannot be dereferenced
错误。
在取消引用周围使用括号解决了优先级问题:
(*mystringval).push_str(sourcePortion.as_str());
*myval += 1
起作用的原因是因为一元 *
的优先级高于 +=
,这意味着它被解析为
(*myval) += 1
因为 or_insert
returns &mut V
,你不需要在调用它的方法之前取消引用它。以下也适用:
mystringval.push_str(sourcePortion.as_str());