函式名: my_counter
輸入: ['foo', 'bar', 'bar', 'bar', 'bar']]
輸出: {'foo': 1, 'bar': 4}
注意:輸出型別是 HashMap<String, usize>,而不是 HashMap<&str, usize>。
這是我的實作,我認為這有點開銷。'bar' 已被轉換為字串四次,但可能不需要。
pub fn my_counter(vec: &Vec<String>) -> HashMap<String, usize> {
let mut result: HashMap<String, usize> = HashMap::new();
for key in vec.iter() {
let val = result.entry(key.to_string()).or_insert(0);
*val = 1;
}
result
}
有人愿意分享更好的解決方案嗎?非常感謝~
uj5u.com熱心網友回復:
您可以做的一件事是String通過使用(或移動)原始向量的值來避免創建新的 s。像這樣:
pub fn my_counter(vec: Vec<String>) -> HashMap<String, usize> {
let mut result: HashMap<String, usize> = HashMap::new();
for key in vec {
let val = result.entry(key).or_insert(0);
*val = 1;
}
result
}
請注意更改后的函式簽名:vecis now Vec<String>, not &Vec<String>。如果出于某種原因,這是不可接受的,那么您真的無法避免為的鍵創建新String值。HashMap假設N是向量項的數量,M是唯一向量項的數量。如果您知道向量中將有很多重復值(即M遠小于N),理論上您可以只創建M new Strings。然而,Rust 似乎并沒有提供穩定的方法來直接實作這一點。如果您可以使用 Nightly,不妨試試raw_entry_mut().
另一種方法可能是首先創建一個臨時的HashMap<&str, usize>,然后將其轉換為所需的“完全擁有” HashMap<String, usize>。然而,這可能只會讓事情變得更糟。這實際上取決于您擁有的密鑰。擁有短鍵和大約 0.5-1.0的M : N比率是一回事,如果你有長鍵并且比率為 0.0001,則完全不同。
如果您對唯一鍵的數量有一個好主意,那么您絕對可以通過簡單地創建HashMapwith來在一定程度上加快速度HashMap::with_capacity(...);。理論上,使用默認哈希的替??代方案也可能有所幫助,盡管我只嘗試過FnvHashMap,即使是短String鍵,我也無法獲得任何顯著的加速。
uj5u.com熱心網友回復:
我可以立即想象 3 種其他變體這樣做
- 首先查看條目是否已經存在
contains_key,然后使用insert或更新get_mut - 只是盲目地
insert,然后重新insert如果第一個插入回傳一個先前的值 HashMap<&str, usize>首先構建一個,然后轉換它(做兩次插入的作業)。
問題是,什么更快取決于輸入資料。有多少個字串,它們有多長,輸入 Vec 有多長。
我對5 個案例進行了基準測驗:
d1:您的簡短示例輸入資料few10k: 10 個長度為 4 的唯一字串,包含 10000 個條目many10k: 10000 個長度≤8 的條目,幾乎都是唯一的long: 300 個長度為 300 的唯一字串mix: 上述所有的
這是結果
測驗 d1_blind ... bench: 331 ns/iter ( /- 5) 測驗 d1_seeing ... bench: 234 ns/iter ( /- 2) 測驗 d1_tushushu ... bench: 230 ns/iter ( /- 4) 測驗 d1_twice ... 作業臺:232 ns/iter ( /- 4) 測驗 few10k_blind ... bench: 727,628 ns/iter ( /- 4,557) 測驗 few10k_seeing ... bench: 302,445 ns/iter ( /- 3,282) 測驗 few10k_tushushu ... bench: 399,378 ns/iter ( /- 3,870) 測驗few10k_twice ... bench: 173,828 ns/iter ( /- 2,431) 測驗 long_blind ... bench: 70,604 ns/iter ( /- 233) 測驗 long_seeing ... bench: 93,349 ns/iter ( /- 381) 測驗 long_tushushu ... bench: 69,862 ns/iter ( /- 231) 測驗 long_twice ... bench: 92,118 ns/iter ( /- 292) 測驗 many10k_blind ... bench: 1,060,656 ns/iter ( /- 65,839) 測驗 many10k_seeing ... bench: 1,148,671 ns/iter ( /- 58,452) 測驗 many10k_tushushu ... bench: 957,733 ns/iter ( /- 5,392) 測驗 many10k_twice ... bench: 1,297,526 ns/iter ( /- 57,415) 測驗 mix_blind ... bench: 1,962,634 ns/iter ( /- 7,973) 測驗 mix_seeing ... bench: 1,617,921 ns/iter ( /- 45,453) 測驗 mix_tushushu ... bench: 1,519,876 ns/iter ( /- 4,872) 測驗 mix_twice ... 作業臺:1,597,130 ns/iter ( /- 11,068)
在大多數情況下,您的實作似乎表現最好。您可以更進一步并開始混合實作,即運行twice直到HashMap<&str, usize>達到一定大小,然后切換到您的實作。由于這個問題出現在很多地方(例如在 sql 資料庫中,而且那些人喜歡優化事物到死),所以有人可能已經在某處寫了一篇關于最佳方法的論文。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/419571.html
標籤:
上一篇:陣列中最長偶數長度子串
