使用 map 将多行 if 语句转换为单行
Convert multi-line if statment to single line with map
注:c++98
我对 C++ 有点陌生,我想清理我的代码。我有一个if语句,检查数组中的数据类型,如果匹配则执行相应的语句。
我想将此多行 if 语句转换为单行,以检查映射中是否存在这些类型,以及它们是否执行。
我的代码:
if (boost::iequals(sqlBufferTypes[i][j], "INTEGER") ||
boost::iequals(sqlBufferTypes[i][j], "INT") ||
boost::iequals(sqlBufferTypes[i][j], "BIGINT") ||
boost::iequals(sqlBufferTypes[i][j], "uint8_t") ||
boost::iequals(sqlBufferTypes[i][j], "uint16_t") ||
boost::iequals(sqlBufferTypes[i][j], "LONG"))
{
// do stuff
}
并希望将其转换为类似于:
map<int, string> dataTypes;
dataTypes[1,"INT"];
dataTypes[2,"BIGINT"];
dataTypes[3,"uint8_t"];
dataTypes[4,"uint16_t"];
dataTypes[5,"LONG"];
if (boost::iequals(dataTypes.begin(), dataTypes.end())
{
// do stuff
}
根据您的描述,我认为您在示例中调换了密钥和 ID。
但是,您可以通过为地图引入自定义比较来相当轻松地完成您想要的操作。一个简单的方法是先创建一个 lambda 函数:
auto compare = [](const std::string& a, const std::string& b) {return boost::iequals(a, b); };
std::map < std::string, int, decltype(compare)> mymap = { {"INT", 1},{"BIGINT", 2 }};//and so on
那么你可以这样做:
if (mymap.count(sqlBufferTypes[i][j])) {//in c++20 can use "contains" instead of "count"
//do stuff
}
如果您只想检查并且以后不需要 ID,那么您应该使用 std::set
而不是地图。
c++98 注
在 c++98 中您不能使用 lambda,但是您仍然可以使用常规结构创建比较谓词:
struct compare : public std::binary_function<string, string, bool>
{
bool operator()(const string& a, const string& b) const
{
return boost::iequals(a,b);
}
};
我想真正的挑战是有一个map<>
不区分大小写地比较键。
您可以通过使用比较谓词来做到这一点:
struct ci_less {
bool operator()(std::string_view a, std::string_view b) const {
return boost::lexicographical_compare(a, b, boost::is_iless{});
}
};
您声明映射以使用该谓词:
std::map<std::string, int, ci_less> const dataTypes {
{ "INT", 1 },
{ "BIGINT", 2 },
{ "uint8_t", 3 },
{ "uint16_t", 4 },
{ "LONG", 5 },
};
Note that it is now const, and I flipped the key/value pairs. See below
一些测试:Live On Coliru
// your sqlBufferTypes[i][j] e.g.:
for (std::string const key : { "uint32_t", "long", "lONg" }) {
if (auto match = dataTypes.find(key); match != dataTypes.end()) {
std::cout << std::quoted(key) << " maps to " << match->second;
// more readable repeats lookup:
std::cout << " or the same: " << dataTypes.at(key) << "\n"; // throws unless found
} else {
std::cout << std::quoted(key) << " not found\n";
}
}
版画
"uint32_t" not found
"long" maps to 5 or the same: 5
"lONg" maps to 5 or the same: 5
翻转Key/Value
字典在所有 languages/libraries 中都有一个用于查找的关键字段。因此,要反向查找,您最终会进行线性搜索(只需查看每个元素)。
在 Boost 中,您可以 通过定义多索引容器来吃蛋糕。
多索引
这可以方便通过多个索引(包括复合键)进行查找。 (搜索我的答案以获得更多现实生活中的例子)
#include <boost/algorithm/string.hpp> // for is_iless et al.
#include <string_view>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <iostream> // for std::cout
#include <iomanip> // for std::quoted
#include <boost/locale.hpp>
namespace bmi = boost::multi_index;
struct ci_less {
bool operator()(std::string_view a, std::string_view b) const {
return boost::lexicographical_compare(a, b, boost::is_iless{});
}
};
struct DbType {
std::string_view name;
int type_id;
friend std::ostream& operator<<(std::ostream& os, DbType const& t) {
return os << "DbType{" << std::quoted(t.name) << ", " << t.type_id << "}";
}
};
using Map = bmi::multi_index_container<
DbType,
bmi::indexed_by<
bmi::ordered_unique<
bmi::tag<struct by_id>,
bmi::member<DbType, int, &DbType::type_id> >,
bmi::ordered_unique<
bmi::tag<struct by_name>,
bmi::member<DbType, std::string_view, &DbType::name>, ci_less>
>
>;
int main() {
Map dataTypes {
{ "INT", 1 },
{ "BIGINT", 2 },
{ "uint8_t", 3 },
{ "uint16_t", 4 },
{ "LONG", 5 },
};
auto& idx = dataTypes.get<by_name>();
// your sqlBufferTypes[i][j] e.g.:
for (std::string_view const key : { "uint32_t", "long", "lONg" }) {
if (auto match = idx.find(key); match != idx.end()) {
std::cout << std::quoted(key) << " -> " << *match << std::endl;
} else {
std::cout << std::quoted(key) << " not found\n";
}
}
}
版画
"uint32_t" not found
"long" -> DbType{"LONG", 5}
"lONg" -> DbType{"LONG", 5}
双图
Boost Bimap 是地图的专业化。它的选项较少,并且特别添加了 operator[]
风格的界面。
using Map = boost::bimap<
int,
boost::bimaps::set_of<std::string_view, ci_less>>;
遗憾的是构造函数不支持初始化列表,但我们可以使用迭代器接口,然后我们使用 bimap 的 right
视图按名称进行查找:
static const Map::relation s_mappings[] = {
{ 1, "INT" },
{ 2, "BIGINT" },
{ 3, "uint8_t" },
{ 4, "uint16_t" },
{ 5, "LONG" },
};
Map const dataTypes { std::begin(s_mappings), std::end(s_mappings) };
// your sqlBufferTypes[i][j] e.g.:
auto& vw = dataTypes.right;
for (std::string_view const key : { "uint32_t", "long", "lONg" }) {
if (auto match = vw.find(key); match != vw.end()) {
std::cout << std::quoted(key) << " -> " << match->second << "\n";
} else {
std::cout << std::quoted(key) << " not found\n";
}
}
版画
"uint32_t" not found
"long" -> 5
"lONg" -> 5
注:c++98
我对 C++ 有点陌生,我想清理我的代码。我有一个if语句,检查数组中的数据类型,如果匹配则执行相应的语句。
我想将此多行 if 语句转换为单行,以检查映射中是否存在这些类型,以及它们是否执行。
我的代码:
if (boost::iequals(sqlBufferTypes[i][j], "INTEGER") ||
boost::iequals(sqlBufferTypes[i][j], "INT") ||
boost::iequals(sqlBufferTypes[i][j], "BIGINT") ||
boost::iequals(sqlBufferTypes[i][j], "uint8_t") ||
boost::iequals(sqlBufferTypes[i][j], "uint16_t") ||
boost::iequals(sqlBufferTypes[i][j], "LONG"))
{
// do stuff
}
并希望将其转换为类似于:
map<int, string> dataTypes;
dataTypes[1,"INT"];
dataTypes[2,"BIGINT"];
dataTypes[3,"uint8_t"];
dataTypes[4,"uint16_t"];
dataTypes[5,"LONG"];
if (boost::iequals(dataTypes.begin(), dataTypes.end())
{
// do stuff
}
根据您的描述,我认为您在示例中调换了密钥和 ID。
但是,您可以通过为地图引入自定义比较来相当轻松地完成您想要的操作。一个简单的方法是先创建一个 lambda 函数:
auto compare = [](const std::string& a, const std::string& b) {return boost::iequals(a, b); };
std::map < std::string, int, decltype(compare)> mymap = { {"INT", 1},{"BIGINT", 2 }};//and so on
那么你可以这样做:
if (mymap.count(sqlBufferTypes[i][j])) {//in c++20 can use "contains" instead of "count"
//do stuff
}
如果您只想检查并且以后不需要 ID,那么您应该使用 std::set
而不是地图。
c++98 注
在 c++98 中您不能使用 lambda,但是您仍然可以使用常规结构创建比较谓词:
struct compare : public std::binary_function<string, string, bool>
{
bool operator()(const string& a, const string& b) const
{
return boost::iequals(a,b);
}
};
我想真正的挑战是有一个map<>
不区分大小写地比较键。
您可以通过使用比较谓词来做到这一点:
struct ci_less {
bool operator()(std::string_view a, std::string_view b) const {
return boost::lexicographical_compare(a, b, boost::is_iless{});
}
};
您声明映射以使用该谓词:
std::map<std::string, int, ci_less> const dataTypes {
{ "INT", 1 },
{ "BIGINT", 2 },
{ "uint8_t", 3 },
{ "uint16_t", 4 },
{ "LONG", 5 },
};
Note that it is now const, and I flipped the key/value pairs. See below
一些测试:Live On Coliru
// your sqlBufferTypes[i][j] e.g.:
for (std::string const key : { "uint32_t", "long", "lONg" }) {
if (auto match = dataTypes.find(key); match != dataTypes.end()) {
std::cout << std::quoted(key) << " maps to " << match->second;
// more readable repeats lookup:
std::cout << " or the same: " << dataTypes.at(key) << "\n"; // throws unless found
} else {
std::cout << std::quoted(key) << " not found\n";
}
}
版画
"uint32_t" not found
"long" maps to 5 or the same: 5
"lONg" maps to 5 or the same: 5
翻转Key/Value
字典在所有 languages/libraries 中都有一个用于查找的关键字段。因此,要反向查找,您最终会进行线性搜索(只需查看每个元素)。
在 Boost 中,您可以 通过定义多索引容器来吃蛋糕。
多索引
这可以方便通过多个索引(包括复合键)进行查找。 (搜索我的答案以获得更多现实生活中的例子)
#include <boost/algorithm/string.hpp> // for is_iless et al.
#include <string_view>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <iostream> // for std::cout
#include <iomanip> // for std::quoted
#include <boost/locale.hpp>
namespace bmi = boost::multi_index;
struct ci_less {
bool operator()(std::string_view a, std::string_view b) const {
return boost::lexicographical_compare(a, b, boost::is_iless{});
}
};
struct DbType {
std::string_view name;
int type_id;
friend std::ostream& operator<<(std::ostream& os, DbType const& t) {
return os << "DbType{" << std::quoted(t.name) << ", " << t.type_id << "}";
}
};
using Map = bmi::multi_index_container<
DbType,
bmi::indexed_by<
bmi::ordered_unique<
bmi::tag<struct by_id>,
bmi::member<DbType, int, &DbType::type_id> >,
bmi::ordered_unique<
bmi::tag<struct by_name>,
bmi::member<DbType, std::string_view, &DbType::name>, ci_less>
>
>;
int main() {
Map dataTypes {
{ "INT", 1 },
{ "BIGINT", 2 },
{ "uint8_t", 3 },
{ "uint16_t", 4 },
{ "LONG", 5 },
};
auto& idx = dataTypes.get<by_name>();
// your sqlBufferTypes[i][j] e.g.:
for (std::string_view const key : { "uint32_t", "long", "lONg" }) {
if (auto match = idx.find(key); match != idx.end()) {
std::cout << std::quoted(key) << " -> " << *match << std::endl;
} else {
std::cout << std::quoted(key) << " not found\n";
}
}
}
版画
"uint32_t" not found
"long" -> DbType{"LONG", 5}
"lONg" -> DbType{"LONG", 5}
双图
Boost Bimap 是地图的专业化。它的选项较少,并且特别添加了 operator[]
风格的界面。
using Map = boost::bimap<
int,
boost::bimaps::set_of<std::string_view, ci_less>>;
遗憾的是构造函数不支持初始化列表,但我们可以使用迭代器接口,然后我们使用 bimap 的 right
视图按名称进行查找:
static const Map::relation s_mappings[] = {
{ 1, "INT" },
{ 2, "BIGINT" },
{ 3, "uint8_t" },
{ 4, "uint16_t" },
{ 5, "LONG" },
};
Map const dataTypes { std::begin(s_mappings), std::end(s_mappings) };
// your sqlBufferTypes[i][j] e.g.:
auto& vw = dataTypes.right;
for (std::string_view const key : { "uint32_t", "long", "lONg" }) {
if (auto match = vw.find(key); match != vw.end()) {
std::cout << std::quoted(key) << " -> " << match->second << "\n";
} else {
std::cout << std::quoted(key) << " not found\n";
}
}
版画
"uint32_t" not found
"long" -> 5
"lONg" -> 5