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

如何在Dart中实现带动态索引的映射(支持日期间隔与插入调整)

实现带动态日期索引的双映射结构

核心设计思路

要满足「按日期快速查询」和「按索引快速获取日期+内容」的需求,同时支持间隔日期、插入早日期时自动调整后续索引,最直接的方案是双映射+有序日期列表:

  • 一个映射负责「日期→内容」的快速查询
  • 另一个映射负责「索引→(日期, 内容)」的快速查询
  • 用有序列表维护所有日期,同时追踪当前最早日期——索引的定义为「当前日期与最早日期的天数差值」,这完全匹配你给出的示例逻辑。

当插入比当前最早日期更早的新日期时,所有已有条目的索引都要加上「新旧最早日期的天数差」,因为它们与新最早日期的差值等于原差值加上这个天数差。

Python 实现示例

from datetime import date
from bisect import insort

class DateIndexedMap:
    def __init__(self):
        self.date_to_content = {}  # 日期到内容的映射
        self.index_to_entry = {}   # 索引到(日期, 内容)的映射
        self.earliest_date = None  # 当前集合中的最早日期
        self.all_dates = []        # 升序存储所有日期,用于快速更新最早日期

    def __getitem__(self, target_date):
        """通过日期获取内容,用法:mymap[date0] -> something0"""
        if target_date not in self.date_to_content:
            raise KeyError(f"日期 {target_date} 不存在")
        return self.date_to_content[target_date]

    def of(self, target_index):
        """通过索引获取日期和内容,用法:mymap.of(index0) -> (date0, something0)"""
        if target_index not in self.index_to_entry:
            raise KeyError(f"索引 {target_index} 不存在")
        return self.index_to_entry[target_index]

    def add(self, new_date, content):
        """添加新条目,自动处理索引调整"""
        # 日期已存在时,更新内容并同步映射
        if new_date in self.date_to_content:
            old_index = (new_date - self.earliest_date).days
            self.date_to_content[new_date] = content
            self.index_to_entry[old_index] = (new_date, content)
            return

        # 将新日期插入有序列表
        insort(self.all_dates, new_date)
        self.date_to_content[new_date] = content

        # 处理第一个条目
        if self.earliest_date is None:
            self.earliest_date = new_date
            self.index_to_entry[0] = (new_date, content)
            return

        # 插入了更早的日期,需要批量调整所有已有索引
        if new_date < self.earliest_date:
            diff = (self.earliest_date - new_date).days
            # 重建索引映射
            new_index_map = {}
            for old_idx, (old_date, old_content) in self.index_to_entry.items():
                new_index_map[old_idx + diff] = (old_date, old_content)
            # 添加新条目(索引为0)
            new_index_map[0] = (new_date, content)
            self.index_to_entry = new_index_map
            self.earliest_date = new_date
        else:
            # 插入的日期不早于当前最早,直接计算索引
            new_index = (new_date - self.earliest_date).days
            self.index_to_entry[new_index] = (new_date, content)

    def remove(self, target_date):
        """可选:删除条目,自动维护最早日期和索引"""
        if target_date not in self.date_to_content:
            raise KeyError(f"日期 {target_date} 不存在")
        
        # 删除映射中的条目
        del self.date_to_content[target_date]
        target_index = (target_date - self.earliest_date).days
        del self.index_to_entry[target_index]
        
        # 从有序列表中移除日期
        self.all_dates.remove(target_date)
        
        # 如果删除的是最早日期,更新最早日期并重建索引
        if target_date == self.earliest_date:
            if not self.all_dates:
                self.earliest_date = None
            else:
                self.earliest_date = self.all_dates[0]
                new_index_map = {}
                for d, content in self.date_to_content.items():
                    idx = (d - self.earliest_date).days
                    new_index_map[idx] = (d, content)
                self.index_to_entry = new_index_map

测试示例(匹配你的需求)

# 初始化实例
mymap = DateIndexedMap()

# 添加初始条目
date0 = date(2023, 3, 14)
mymap.add(date0, "something0")
date1 = date(2023, 5, 10)
mymap.add(date1, "something56")

# 查询初始状态
print(mymap.of(0))       # 输出:(datetime.date(2023, 3, 14), 'something0')
print(mymap.of(57))      # 输出:(datetime.date(2023, 5, 10), 'something56')(实际天数差为57)

# 添加更早的日期
date_new = date(2023, 3, 12)
mymap.add(date_new, "somethingNew")

# 查询调整后的状态
print(mymap.of(0))       # 输出:(datetime.date(2023, 3, 12), 'somethingNew')
print(mymap.of(2))       # 输出:(datetime.date(2023, 3, 14), 'something0')
print(mymap.of(59))      # 输出:(datetime.date(2023, 5, 10), 'something56')(57+2=59)

跨语言迁移思路

这个方案可以轻松适配其他语言:

  • Dart/Flutter:用Map<DateTime, T>和Map<int, (DateTime, T)>,通过DateTime.difference计算天数差,用List<DateTime>维护有序日期(插入时手动排序或用第三方库)。
  • JavaScript:用Map存储映射,日期可以转成ISO字符串作为键(避免引用类型问题),天数差通过Math.floor((date2 - date1) / (1000 * 60 * 60 * 24))计算。
  • Java:用TreeMap<LocalDate, T>维护有序日期,搭配HashMap<Integer, Map.Entry<LocalDate, T>>存储索引映射,插入早日期时遍历TreeMap更新索引。

效率说明

  • 日常查询(按日期/索引)的时间复杂度为O(1),效率极高。
  • 插入更早日期时需要遍历所有条目更新索引,时间复杂度为O(n),如果不是频繁插入早日期,完全可以接受;若需要优化,可以考虑用树结构维护索引,但会增加实现复杂度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 03:02:04