之前的一篇博客讨论了使用lower_bound来查询配置区间。
https://www.cnblogs.com/demon90s/p/15658800.html
由于配置设计的原因,从字段上面是无法看的出键所在的段的。比如:
std::map<int, std::vector<std::string>> day_to_workings_map =
{
{4, { "study", "sleep", "play" }},// 第4天之前
{10, { "movie", "travel", "eat" }},// 第5天到第10天
{20, { "interview", "go home", "watch foot ball" }}, // 第11天到第20天
};
如果 day = 5 ,那么想要知道5所在的区间的话,光读取到配置是不够的。还需要做更多的工作。这里要考虑几种情况:
- day小于第一个配置
- day大于第一个配置小于等于最大的配置
- day大于最大的配置
第三种情况则无法得到所在的段。属于失败的情况。第一种则需要提供一个下限的默认值,通常是1。
第二种情况则需要得到当前遍历迭代器的上一个迭代器位置,如何得到?可以使用 std::prev
方便的获取。
函数如:
bool GetDayRange(int day, int& lower, int& upper)
{
auto it = day_to_workings_map.lower_bound(day);
if (it != day_to_workings_map.end())
{
if (it == day_to_workings_map.begin())
{
lower = 1;
upper = it->first;
return true;
}
else
{
auto pre_it = std::prev(it, 1);
lower = pre_it->first + 1;
upper = it->first;
return true;
}
}
return false;
}
完整测试代码如:
std::map<int, std::vector<std::string>> day_to_workings_map =
{
{4, { "study", "sleep", "play" }},// 第4天之前
{10, { "movie", "travel", "eat" }},// 第5天到第10天
{20, { "interview", "go home", "watch foot ball" }}, // 第11天到第20天
};
const std::vector<std::string>* GetWorkList(int day, int *hit_day)
{
auto it = day_to_workings_map.lower_bound(day);
if (it != day_to_workings_map.end())
{
if (hit_day != nullptr) *hit_day = it->first;
return &it->second;
}
return nullptr;
}
bool GetDayRange(int day, int& lower, int& upper)
{
auto it = day_to_workings_map.lower_bound(day);
if (it != day_to_workings_map.end())
{
if (it == day_to_workings_map.begin())
{
lower = 1;
upper = it->first;
return true;
}
else
{
auto pre_it = std::prev(it, 1);
lower = pre_it->first + 1;
upper = it->first;
return true;
}
}
return false;
}
int main()
{
int input_day = 0;
std::cout << "input day: ";
while (std::cin >> input_day)
{
int hit_day = 0;
auto work_list = GetWorkList(input_day, &hit_day);
if (nullptr != work_list)
{
int lower = 0;
int upper = 0;
GetDayRange(input_day, lower, upper);
std::cout << "hit day: " << hit_day << "[" << lower << ", " << upper << "]" << std::endl;
std::cout << "work:";
for (const auto& work : *work_list)
{
std::cout << " " << work;
}
std::cout << "\n";
}
else
{
std::cout << "invalid day" << std::endl;
}
std::cout << "input day: ";
}
std::cin.get();
}