2016-05-01 5 views
1

私はアイテムのコレクションを繰り返し表示しています。そのアイテムをキーとし、元のコレクションに何回出現させるかを数えたHashMapを作成します。値の集まりを数えるHashMapに変換するにはどうすればよいですか?

私が取り組んでいる具体例は、各文字が何回出現するかを数えたいところです。

は、私はこのような何かを行うことができます:

fn into_character_map(word: &str) -> HashMap<char, i32> { 
    let mut characters = HashMap::new(); 

    for c in word.chars() { 
     let entry = characters.entry(c).or_insert(0); 
     *entry += 1; 
    } 

    characters 
} 

しかし、よりエレガントな解決策があるかどう私は思っていました。私はcollect()を使用することを考えていましたが、アイテム間の状態を維持していないので、必要なものをサポートしていないようです。

これは私が'Anagram' problem on Exercismに私の解決策を書いていたときに出てきました。

答えて

3

それはエレガント以上だ場合、それは疑わしいですが、folding using a HashMapが少ない行が必要です:あなたが他の人にアイテムの種類をカウントする必要がある場合は

fn into_character_map(word: &str) -> HashMap<char, i32> { 
    word.chars().fold(HashMap::new(), |mut acc, c| { 
     *acc.entry(c).or_insert(0) += 1; 
     acc 
    }) 
} 
0

を、あなたはCounter構造体を作成することができます

use std::collections::HashMap; 
use std::hash::Hash; 
use std::iter::FromIterator; 

#[derive(Debug)] 
pub struct Counter<K: Hash + Eq> { 
    map: HashMap<K, usize> 
} 

impl<K: Hash + Eq> Counter<K> { 
    pub fn new() -> Self { 
     Counter { map: HashMap::new() } 
    } 

    pub fn get(&self, key: &K) -> usize { 
     if let Some(v) = self.map.get(key) { 
      *v 
     } else { 
      0 
     } 
    } 

    pub fn get_mut(&mut self, key: K) -> &mut usize { 
     &mut *self.map.entry(key).or_insert(0) 
    } 

    pub fn inc(mut self, key: K) -> Self { 
     *self.get_mut(key) += 1; 
     self 
    } 
} 

impl<K: Hash + Eq> FromIterator<K> for Counter<K> { 
    fn from_iter<T>(iterator: T) -> Self where T: IntoIterator<Item=K> { 
     iterator.into_iter().fold(Counter::new(), Counter::inc) 
    } 
} 

fn main() { 
    println!("{:?}", Counter::from_iter("test".chars())); 
    println!("{:?}", Counter::from_iter(vec![3, 3, 2, 3].into_iter())); 
} 

出力

Counter { map: {'e': 1, 't': 2, 's': 1} } 
Counter { map: {2: 1, 3: 3} } 
関連する問題