【问题标题】:Sort HashMap data by value按值对 HashMap 数据进行排序
【发布时间】:2016-01-01 11:45:56
【问题描述】:

我想在 Rust 中按值对 HashMap 数据进行排序(例如,在计算字符串中的字符频率时)。

我正在尝试做的 Python 等价物是:

count = {}
for c in text:
    count[c] = count.get('c', 0) + 1

sorted_data = sorted(count.items(), key=lambda item: -item[1])

print('Most frequent character in text:', sorted_data[0][0])

我对应的 Rust 代码如下所示:

// Count the frequency of each letter
let mut count: HashMap<char, u32> = HashMap::new();
for c in text.to_lowercase().chars() {
    *count.entry(c).or_insert(0) += 1;
}

// Get a sorted (by field 0 ("count") in reversed order) list of the
// most frequently used characters:
let mut count_vec: Vec<(&char, &u32)> = count.iter().collect();
count_vec.sort_by(|a, b| b.1.cmp(a.1));

println!("Most frequent character in text: {}", count_vec[0].0);

这是惯用的 Rust 吗?我能否以某种方式构造count_vec,以便它能够使用并拥有HashMaps 数据(例如,使用map())?这会更符合规范吗?

【问题讨论】:

  • 我猜你的意思是“按字段 1”? (在您的评论中)

标签: rust


【解决方案1】:

这是惯用的 Rust 吗?

没有什么特别的unidiomatic,除了count_vec 上不必要的完整类型约束可能;你可以使用

let mut count_vec: Vec<_> = count.iter().collect();

从上下文中不难确定count_vec 的完整类型是什么。你也可以省略count的类型约束完全,但是你必须用你的整数文字玩恶作剧才能推断出正确的值类型。也就是说,在这种情况下,显式注释是非常合理的。

其他你可以做的边界改变如果你愿意的话是使用|a, b| a.1.cmp(b.1).reverse()进行排序关闭。 Ordering::reverse 方法只是反转结果,使小于变为大于,反之亦然。这使得您意思您所写的内容更加明显,而不是意外地调换了两个字母。

我能否以某种方式构造 count_vec 以便它使用 HashMaps 数据并拥有它?

没有任何意义。仅仅因为HashMap 正在使用内存并不意味着内存在任何方面都与Vec 兼容。您可以使用count.into_iter()使用 HashMap 并将元素移出(而不是迭代指针),但由于charu32 都可以轻松复制,所以这不会真的没有任何收获。

【讨论】:

    【解决方案2】:

    这可能是解决问题的另一种方式,无需中间媒介。

    // Count the frequency of each letter
    let mut count: HashMap<char, u32> = HashMap::new();
    for c in text.to_lowercase().chars() {
        *count.entry(c).or_insert(0) += 1;
    }
    
    let top_char = count.iter().max_by(|a, b| a.1.cmp(&b.1)).unwrap();
    
    println!("Most frequent character in text: {}", top_char.0);
    

    【讨论】:

      【解决方案3】:

      使用BTreeMap 排序数据

      BTreeMap 默认按key 对其元素进行排序,因此交换键和值的位置并将它们放入BTreeMap

      let count_b: BTreeMap<&u32,&char> = count.iter().map(|(k,v)| (v,k)).collect();
      

      应该给你一个根据字符频率排序的地图。
      但是会丢失一些相同频率的字符。但如果你只想要最频繁出现的字符,那也没关系。

      你可以得到结果使用

      println!("Most frequent character in text: {}", count_b.last_key_value().unwrap().1);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-05
        • 2011-12-28
        • 1970-01-01
        • 1970-01-01
        • 2023-04-06
        • 2019-04-08
        • 2018-06-06
        • 2015-12-04
        相关资源
        最近更新 更多