Convert multi-line if statment to single line with map

jabroni

Note: c++98

I am a little new to C++ and I want to clean my code up. I have an if statment that checks the data type in an array, and if it matches then it is to execute the corresponding statement.

I want to convert this multi-line if statment to a single line that checks if any of these types exist in the map, and if they do execute it.

My code:

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
            }

and would like to convert it similar to something like:

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
}
sehe

I suppose the real challenge is to have a map<> that compares the keys case-insensitively.

You do that by using a comparison predicate:

struct ci_less {
    bool operator()(std::string_view a, std::string_view b) const {
        return boost::lexicographical_compare(a, b, boost::is_iless{});
    }
};

You declare the map to use that predicate:

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

Some tests: 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";
    }
}

Prints

"uint32_t" not found
"long" maps to 5 or the same: 5
"lONg" maps to 5 or the same: 5

Flipping Key/Value

Dictionaries have a key field for lookup in all languages/libraries. So, to lookup in reverse you end up doing a linear search (just look at each element).

In Boost you can have your cake and eat it by defining a Multi Index Container.

Multi Index

This can facilitate lookup by multiple indices, including composite keys. (Search my answers for more real-life examples)

Live On Coliru

#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";
        }
    }
}

Prints

"uint32_t" not found
"long" -> DbType{"LONG", 5}
"lONg" -> DbType{"LONG", 5}

Bimaps

Boost Bimap is a specialization of that for maps. It has fewer options, and notably adds operator[] style interface back.

using Map = boost::bimap<
    int,
    boost::bimaps::set_of<std::string_view, ci_less>>;

Sadly the constructor doesn't support initializaer lists, but we can use the iterator interface, and then we use the right view of the bimap to do lookups by name:

Live On Coliru

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";
    }
}

Prints

"uint32_t" not found
"long" -> 5
"lONg" -> 5

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

convert multi line string to single line

Jenkins convert multi line variable to single line

Bash: Commands to Convert Multi Lines to Single Line

Convert multi lines to single line with spaces and quotes

Convert single line RSA private ssh key to multi line

Convert this single-line nested for loop to multi-line in python

Convert multilines to single line

How to match both multi line and single line

Write multi-line statement on single line

Change Multi line strings to Single line

Replace single line into multi line python

How can I convert multi-line Python code to a single line?

Convert cURL multi-line output to single, semi-colon-separated line

How to convert a huge single line json file to a multi line file without opening it?

How to convert a multi-line text file into a single line text file

How to convert Multi-line code to single line in Visual Studio Code in Ubuntu

How to convert multi line INI file to single line INI file in Python?

How can I convert a single-line array into a multi-line array?

How to convert a multi line string input from an textbox (in a userform) to a single line input string (vba word)

How to convert JS multi-line string to single-line with tabs

convert multiple line text to single line in R

Convert multilines to single line with SED

How to convert the output into a single line

conditional expression in one line if statment

How to convert declarations placed on a single line to multi-liners using regex?

Makefile multi line variable, single command

How to merge multi-line output to form a single line?

Pandas: from multi-line to single line observations

Python Module Import: Single-line vs Multi-line