如何在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
相关产品推荐
相关产品推荐

