使用std::map及其upper_bound函数很容易实现。 使用每个范围的下限作为Map的键。Map类型的对应值是{lower bound, upper bound, and item}的三元组。然后,要基于特定值查找对象,请调用map::upper_bound并查找Map中“超过”匹配项的项。然后,“返回1”并测试它是否匹配。
#include <algorithm>
#include <iostream>
#include <map>
template <typename T>
struct RangeAndValue
{
int low;
int high;
T value;
};
template <typename T>
struct RangeTable
{
std::map<int, RangeAndValue<T>> table;
void Insert(int low, int high, const T& t)
{
table[low] = {low, high, t};
}
bool Lookup(int value, T& t)
{
auto itor = table.upper_bound(value);
if (itor != table.begin())
{
itor--;
if ((value >= itor->second.low) && (value <= itor->second.high))
{
t = itor->second.value;
return true;
}
}
return false;
}
};
概念验证(使用0-10Map到a、11-20Map到B和21-30Map到c的样本范围)
int main()
{
RangeTable<std::string> rangeTable;
rangeTable.Insert(0, 10, "a");
rangeTable.Insert(11,20, "b");
rangeTable.Insert(21,30, "c");
for (int i = -1; i < 32; i++)
{
std::string s;
bool result = rangeTable.Lookup(i, s);
std::cout << i << " : " << (result ? s : "<not found>") << std::endl;
}
return 0;
}
运行时产生预期结果:
$ g++ main.cpp -o testapp
$ ./testapp
-1 : <not found>
0 : a
1 : a
2 : a
3 : a
4 : a
5 : a
6 : a
7 : a
8 : a
9 : a
10 : a
11 : b
12 : b
13 : b
14 : b
15 : b
16 : b
17 : b
18 : b
19 : b
20 : b
21 : c
22 : c
23 : c
24 : c
25 : c
26 : c
27 : c
28 : c
29 : c
30 : c
31 : <not found>
#include <compare>
#include <iostream>
#include <map>
#include <string>
template <typename T>
struct Range
{
T begin{}, end{};
friend constexpr auto operator<=>(const Range &, const Range &) = default;
friend constexpr std::weak_ordering operator<=>(const Range &a, T b)
{
if (b < a.begin)
return std::weak_ordering::greater;
else if (b > a.end)
return std::weak_ordering::less;
else
return std::weak_ordering::equivalent;
}
};
int main()
{
std::map<Range<int>, std::string, std::less<>> m = {
{{0, 5}, "A"},
{{6, 10}, "B"},
{{11, 15}, "C"},
};
auto check = [&](int n)
{
auto it = m.find(n);
if (it != m.end())
std::cout << n << " -> " << it->second << '\n';
else
std::cout << n << " not in the map\n";
};
check(0); // A
check(1); // A
check(5); // A
check(6); // B
check(-1); // not in the map
check(16); // not in the map
}
首先,我们使用std::less<>(没有模板参数-透明版本),它使.find()成为一个模板,接受与键类型类似的任何类型。 接下来我们创建一个range类,它重载了与自身和元素类型的比较操作符(使用C++20)。 您可以对std::pair和一个定制的透明比较器(add using is_transparent = void;)执行相同的操作,该比较器可以正确地将其与数字进行比较。
2条答案
按热度按时间f0ofjuux1#
使用std::map及其upper_bound函数很容易实现。
使用每个范围的下限作为Map的键。Map类型的对应值是
{lower bound, upper bound, and item}
的三元组。然后,要基于特定值查找对象,请调用map::upper_bound并查找Map中“超过”匹配项的项。然后,“返回1”并测试它是否匹配。概念验证(使用
0-10
Map到a、11-20
Map到B和21-30
Map到c的样本范围)运行时产生预期结果:
b1uwtaje2#
与@selbie的答案的想法相同,但使用transparent comparator以避免将map Package 在自己的类中:
首先,我们使用
std::less<>
(没有模板参数-透明版本),它使.find()
成为一个模板,接受与键类型类似的任何类型。接下来我们创建一个range类,它重载了与自身和元素类型的比较操作符(使用C++20)。
您可以对
std::pair
和一个定制的透明比较器(addusing is_transparent = void;
)执行相同的操作,该比较器可以正确地将其与数字进行比较。