簡體   English   中英

如何在Rust的哈希表中追加字符串值?

[英]How to append to string values in a hash table in Rust?

我的源文件包含給定日期許多產品的文本CSV行。 我想使用Rust來整理這些文件,以便最終得到許多新的目標CSV文件,每個產品一個,每個文件包含僅特定於該產品的行的一部分。

我當前的解決方案是遍歷源文件的行,並使用HashMap<String, String>收集每個產品的行。 我拆分了每個源代碼行,並使用包含產品ID的元素作為鍵,以在我的HashMap獲得一個Entry (已占用或空閑)。 如果它是空的,我將使用一個新的String初始化該值,該String會預先分配給定的容量,以便以后可以有效地附加到該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返回() ,您得到了() cannot be dereferenced錯誤。

在取消引用周圍使用括號可解決優先級問題:

(*mystringval).push_str(sourcePortion.as_str());

*myval += 1起作用的原因是因為一元*的優先級高於+= ,這意味着它被解析為

(*myval) += 1

由於or_insert返回&mut V ,因此您無需在調用其方法之前對其進行解除引用。 以下內容也適用:

mystringval.push_str(sourcePortion.as_str());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM