如何依次遍历HashMap的键

Tim*_*mmm 1 hashmap rust

我想HashMap按顺序遍历a的键。有没有一种优雅的方法可以做到这一点?我能想到的最好的是:

use std::collections::HashMap;

fn main() {
    let mut m = HashMap::<String, String>::new();

    m.insert("a".to_string(), "1".to_string());
    m.insert("b".to_string(), "2".to_string());
    m.insert("c".to_string(), "3".to_string());
    m.insert("d".to_string(), "4".to_string());

    let mut its = m.iter().collect::<Vec<_>>();
    its.sort();

    for (k, v) in &its {
        println!("{}: {}", k, v);
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望能够执行以下操作:

for (k, v) in m.iter_sorted() {
}
for (k, v) in m.iter_sorted_by(...) {
}
Run Code Online (Sandbox Code Playgroud)

显然,我可以写一个特质来做到这一点,但是我的问题是这样的事情已经存在了吗?

编辑:另外,由于人们指出BTreeMap已经进行了排序,所以我可能应该注意,虽然这是正确的,但实际上并没有HashMap后面跟进的速度快sort()(只要您只对它进行一次排序)。以下是一些随机u32->u32地图的基准测试结果:

哈希图与btreemap

此外,BTreeMap仅允许单个排序顺序。

Inl*_*ine 5

HashMap不保证特定的迭代顺序。实现一致顺序的最简单方法是使用BTreeMap基于的B-tree数据进行排序。

您应该理解,任何实现都将在O(n)内存中执行此操作,尤其是存储对所有项目的引用,并至少需要O(n * log(n))时间来整理数据。

如果您了解这样做的成本,则可以IterTools::sorteditertools板条箱中使用。

use itertools::Itertools; // 0.8.2
use std::collections::HashMap;

fn main() {
    let mut m = HashMap::<String, String>::new();

    m.insert("a".to_string(), "1".to_string());
    m.insert("b".to_string(), "2".to_string());
    m.insert("c".to_string(), "3".to_string());
    m.insert("d".to_string(), "4".to_string());

    println!("{:#?}", m.iter().sorted())
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接

  • @Timmmm“插入排序”通常是指O(_n_²)算法对数组进行适当排序。在_BTreeMap中插入_n_元素的方式在本质上是不同的,并且时间复杂度为O(_n_ log _n_)。如果您甚至需要一次订购数据,我都会选择一个“ BTreeMap”,它肯定更简单,而且也可能更快。 (2认同)