You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过部分键从键类型为(i64,usize)的HashMap中取值?

问题

我有一个键类型为(i64, usize)的HashMap,需要仅通过键元组的第一部分检索对应数据。例如要获取所有键第一部分为-1的条目(即示例中归属-1的所有居民数据)。目前做法是遍历整个HashMap并手动检查键的第一部分,代码如下:

use std::collections::HashMap;

fn main(){
    let mut hmap: HashMap<(i64,usize), &str> = HashMap::new();
    hmap.insert((-1,0), "Oth -1 Resident");
    hmap.insert((-1,1), "1st -1 Resident");
    hmap.insert((-1,2), "2nd -1 Resident");
    
    hmap.insert((1,0), "Oth 1 Resident");
    hmap.insert((1,1), "1st 1 Resident");
    hmap.insert((1,2), "2nd 1 Resident");

    for (k,v) in &hmap {
        if k.0 == -1 {
            println!("{:?}",v);
        } 
    }
}

请问是否存在更优实现方式?


更优实现方案

方案1:重构为嵌套HashMap

最直接的优化是调整数据结构,使用HashMap<i64, HashMap<usize, &str>>。这样可以通过第一部分键直接定位到对应子集合,查询时间复杂度从全量遍历的O(n)降到O(1)(定位子Map)+ O(m)(遍历子Map条目,m为该键对应的条目数),效率提升显著。

示例代码:

use std::collections::HashMap;

fn main() {
    let mut hmap: HashMap<i64, HashMap<usize, &str>> = HashMap::new();
    
    // 插入数据
    hmap.entry(-1).or_default().insert(0, "Oth -1 Resident");
    hmap.entry(-1).or_default().insert(1, "1st -1 Resident");
    hmap.entry(-1).or_default().insert(2, "2nd -1 Resident");
    
    hmap.entry(1).or_default().insert(0, "Oth 1 Resident");
    hmap.entry(1).or_default().insert(1, "1st 1 Resident");
    hmap.entry(1).or_default().insert(2, "2nd 1 Resident");
    
    // 检索第一部分为-1的所有条目
    if let Some(residents) = hmap.get(&-1) {
        for (_, v) in residents {
            println!("{:?}", v);
        }
    }
}

方案2:使用BTreeMap做范围查询

如果不想改动原有数据结构设计,可以改用BTreeMap。Rust中元组的排序规则是优先比较第一个元素,再比较第二个,因此可以通过范围查询直接筛选出所有第一部分键匹配的条目,避免全量遍历。

示例代码:

use std::collections::BTreeMap;

fn main() {
    let mut bmap: BTreeMap<(i64, usize), &str> = BTreeMap::new();
    bmap.insert((-1,0), "Oth -1 Resident");
    bmap.insert((-1,1), "1st -1 Resident");
    bmap.insert((-1,2), "2nd -1 Resident");
    
    bmap.insert((1,0), "Oth 1 Resident");
    bmap.insert((1,1), "1st 1 Resident");
    bmap.insert((1,2), "2nd 1 Resident");
    
    // 范围查询:所有键的第一部分为-1的条目
    let range = bmap.range((-1, usize::MIN)..=(-1, usize::MAX));
    for (_, v) in range {
        println!("{:?}", v);
    }
}

方案对比

  • 嵌套HashMap:查询效率最高,适合频繁按第一部分键检索的场景,但插入操作需要多一层处理,数据结构稍复杂。
  • BTreeMap:无需修改原有结构设计,范围查询效率优于全量遍历,但整体读写性能略低于HashMap(BTree为有序结构,操作复杂度为O(log n))。

内容的提问来源于stack exchange,提问作者Sreyas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:53:12