如何按插入顺序对地图进行排序?

How do I sort a map by order of insertion?

我已经尝试使用 HashMapBTreeMap 来解决这个问题,但都没有用:

use std::collections::{BTreeMap, HashMap};

fn main() {
    let mut btreemap = BTreeMap::new();
    println!("BTreeMap");
    btreemap.insert("Z", "1");
    btreemap.insert("T", "2");
    btreemap.insert("R", "3");
    btreemap.insert("P", "4");
    btreemap.insert("K", "5");
    btreemap.insert("W", "6");
    btreemap.insert("G", "7");
    btreemap.insert("C", "8");
    btreemap.insert("A", "9");
    btreemap.insert("D", "0");
    for (key, value) in btreemap {
        println!("{} {}", key, value);
    }
    println!("Hash Map");
    let mut hashmap = HashMap::new();
    hashmap.insert("Z", "1");
    hashmap.insert("T", "2");
    hashmap.insert("R", "3");
    hashmap.insert("P", "4");
    hashmap.insert("K", "5");
    hashmap.insert("W", "6");
    hashmap.insert("G", "7");
    hashmap.insert("C", "8");
    hashmap.insert("A", "9");
    hashmap.insert("D", "0");
    for (key, value) in hashmap {
        println!("{} {}", key, value);
    }
}

当我通过 Rust playground 运行 时,我得到的结果未按插入顺序排序; BTreeMap 似乎是按字母顺序排列的(打印 A C D G K P R T W Z,连同数字),HashMap 似乎是随机排列的(打印 Z A C D R P T G WK )。

我查看了 Rust 标准库文档,没有看到任何其他映射。

默认集合不跟踪插入顺序。如果您希望按此排序,您需要找到 追踪它的不同合集,或者您自己追踪它。

关联容器(将键映射到值的容器)通常使用以下两种策略之一来高效地查找键:

  • 他们要么根据一些比较操作对键进行排序
  • 或者他们根据一些散列操作散列密钥

在这里,您有两个原型:BTree 对键进行排序,HashMap 对它们进行哈希处理。


如果您只是希望跟踪插入顺序,那么关联容器是容器的错误选择,您想要的是序列容器,例如std::vec::Vec: 始终将项目推到最后,您可以按照插入的顺序迭代它们。

注意:我建议编写一个包装器以防止在其他任何地方插入不需要的内容。


如果,另一方面,你想要一个关联容器跟踪插入顺序,那么你所要求的在 Rust 中还不存在我知道。

在 C++ 中,首选解决方案称为 Boost.MultiIndex,它允许您创建一个可以通过多种不同方式查询的容器;这是一个相当复杂的软件,如果您浏览它的源代码,您就会看到自己的身影。它可能会及时出现在 Rust 中,但如果你现在需要某些东西,我担心你将不得不手动推出你自己的解决方案;您可以将 Boost 代码用作精益求精,尽管根据经验可能很难 read/understand.

None 的标准库集合保持一致的顺序。您可以改用 indexmap 包中的 IndexMap,只要您不调用 remove.

,它就会保留插入顺序
use indexmap::indexmap;

let map = indexmap! {
    "Z" => 1,
    "T" => 2,
    "R" => 3,
    "P" => 4,
    "K" => 5,
    "W" => 6,
};
    
for (k, v) in map {
    println!("{}: {}", k, v);
}

// Z: 1
// T: 2
// R: 3
// P: 4
// K: 5
// W: 6

它通过存储散列 table 来实现这一点,其中键值对的迭代顺序与键的散列值无关。这意味着查找可能 比标准 HashMap,但迭代和删除非常