Print like a dataframe vector pairs c++ - c++

I have a map:
std::map<string , double> params{{a , 1}, {b, 6 }, {c, 7}{d,8} }
I want to print it like a python dataframe:
a b c d
1 6 7 8
Also, I dont want it to run twice.
void join_parameters(std::pair<string , double> param){
std::map<string , double> params;
params.insert(param);
for(const auto& elem : params)
{
double a, b , c,d;
if (elem.first =="a"){
a = elem.second; }
else if (elem.first =="b"){
b = elem.second;}
else if (elem.first =="c"){
c = elem.second; }
else {
d = elem.second;
}
}
std::cout << "d " << "a "<< "b " << "c "<< "\n" << d << a << b << c <<std::endl ;
}
Do you have any suggestion for me?

Your code only works for a map with 4 elements and it assumes that those elements have keys "a" till "d". If that is the case then I would suggest you to use a different data structure, for example
struct params_t {
double a,b,c,d;
};
If you do need the map then you should not make assumptions about number of elements or their keys.
You can use two strings to accumulate the two lines of output in a single loop:
#include <map>
#include <string>
#include <utility>
#include <iostream>
int main() {
std::map<std::string , int> params{{"a" , 1}, {"b", 6 }, {"c", 7},{"d",8} };
std::pair<std::string,std::string> lines;
for (const auto& e : params) {
lines.first += e.first + " ";
lines.second += std::to_string(e.second) + " ";
}
std::cout << lines.first << '\n';
std::cout << lines.second << '\n';
}
Note that I changed the mapped type to int because it looks like you want to store integers. For double you need to adjust the code to get propper formatting.

Related

How to give Default Argument of Std::Vector of std::pairs?

I don't know how many inputs will come to my function as pair of ints. So in order to achieve that I would like to get a default parameter of std::vector of std::pair, because I want at least one pair in case there is no input. How Can I achieve this?
#include <iostream>
#include <string>
void default_function(int inp1 = 11, int inp2 = 13){ //, std::vector<std::pair<int,int>> defaultVector = XXXX
}
int main()
{
default_function();
return 0;
}
For example user can input no pairs in that case I will set them 0,0. They can input (0 , 2) as one pair, or (0 , 5), (2 , 2),(0 , 2) as three or more pairs. How to handle this?
(C++ 14 Version)
Use an initializer list as shown below
void default_function(
std::vector<std::pair<int,int>> v =
{{1,2}, {3,4}, {5,6}})
{
for(auto &p: v)
std::cout << p.first << ", " << p.second << " : ";
}
int main() {
default_function();
return 0;
}

C++ Utility to convert long switch statement into the concise function call which encapsulates the switch case ladder

I want to write a C++ utility which can do the following:
Current Workflow
int num;
std::string str;
switch(num){
case 2:
str = "two";
break;
case 5:
str = "five";
break;
case 7:
str = "seven";
break;
}
I want to achieve this:
//key is always guaranteed to be int but value can be anything
DECLARE_SWITCH( {
{2 , "two"},
{5 , "five"},
{7 , "seven"}
})
int num = 5;
std::string str;
match(num,str,ARR);
//here str == "five"
I want to write the DECLARE_SWITCH and match functions. There is no restriction on the language constructs - preprocessor MACRO, templates anything would do.However, it would be good if there is some simple solution or trick. I know about associative data structures but I do not want to use any data structure. This question is specifically about using switch case.
With the map you can even make the code look very similar to your original sample
#include <map>
#include <string>
#include <iostream>
int main()
{
std::map<int,std::string> DECLARE_SWITCH {
{2 , "two"},
{5 , "five"},
{7 , "seven"}
};
int num = 5;
std::string str = DECLARE_SWITCH[num];
std::cout << str << '\n';
return 0;
}
Note that operator [] will insert new entry to map if it is not present.
To avoid such behavior you will have to use find
#include <map>
#include <string>
#include <iostream>
std::string match(int number, const std::map<int,std::string>& DECLARE_SWITCH )
{
auto q = DECLARE_SWITCH.find(number);
if (q==DECLARE_SWITCH.end()) {
return "";
}
else
return q->second;
}
int main()
{
const std::map<int,std::string> DECLARE_SWITCH {
{2 , "two"},
{5 , "five"},
{7 , "seven"}
}; //now we can declare map as const
int num = 5;
std::string str = match(num,DECLARE_SWITCH);
std::cout << str << '\n';
return 0;
}
std::map / std::unordered_map is ideal for this usecase.
Maps are associative containers that store elements formed by a combination of a key value and a mapped value, following a specific order.
In your case you need key to be an int and mapped value std::string.
Here is an example
std::map<int, std::string> t;
t[1] = "one";
t[2] = "two";
t[3] = "three";
std::cout << "Value for '2': " << t[2] << std::endl;
for (auto& it : t)
{
std::cout << it.first << ": " << it.second << std::endl;
}
for (auto& it : t)
{
if (it.second == "one")
{
std::cout << "Value mapped to 'one' is: " << it.first << std::endl;
}
}
Output
Value for '2': two
1: one
2: two
3: three
Value mapped to 'one' is: 1
In your case
std::map<int, std::string> DECLARE_SWITCH
{
{2 , "two"},
{5 , "five"},
{7 , "seven"}
};
int num = 2;
std::string str = DECLARE_SWITCH[num];
std::cout << str << '\n';
Hmm your looking for the X macro
WARNING CONCEPT CODE NOT TESTET
#define LIST_OF_VARIABLES \
X(2 , "two") \
X(5 , "five") \
X(7 , "seven")
template<class RetValue>
RetValue match(int key) {
#define SWITCH(CASE, VALUE) case CASE : return VALUE;
#define X(PAIR) SWITCH(PAIR)
// makes the actual switch case
switch(key) {
LIST_OF_VARIABLES
default: throw "fail";
}
#undef SWITCH
#undef X
}
int main()
int num = 5;
std::string str;
str = match<std::string>(num);
std::cout << str;
}

How sort double vector according to changes in first vector?

I would like to implement something like DoubleVector.
In this class I would also like to implement sort method, which sort v1_ and according to changes in v1_ the order in v2_ will also change.
The code is below:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class DoubleVector
{
vector<int> v1_;
vector<char> v2_;
public:
void sort()
{
//sort v1_ and also change order in v2_ according to changes in v1_
std::sort(v1_.begin(), v1_.end() /*, lambda ?*/);
}
void add(int value_v1, char value_v2)
{
v1_.push_back(value_v1);
v2_.push_back(value_v2);
}
void print()
{
const auto size = v1_.size();
for (size_t i=0;i<size;++i)
{
cout << v1_[i] << " " << v2_[i] << endl;
}
}
};
int main()
{
DoubleVector dv;
dv.add(6, 'g');
dv.add(2, 'r');
dv.add(3, 'y');
dv.add(4, 'a');
cout << "Before sort:" << endl;
dv.print();
dv.sort();
cout << "After sort:" << endl;
dv.print();//the values in v2_ are in the same order they don't change order according to v1_ changes
return 0;
}
As you can see DoubleVector before sort contains:
6 g
2 r
3 y
4 a
And after sort contains:
2 g
3 r
4 y
6 a
I would like to get:
2 r
3 y
4 a
6 g
So the first vector v1_ has been sorted, but the second still has got the same order and I would like to change order of elements in second v2_ vector according to changes in v1_.
I can write it, but I would like to do it in a fast and clean way, maybe using lambda as third argument in std::sort function? Vectors v1_ and v2_ in class DoubleVector must stay as they are.
Thank you very much.
Make a vector of std::pair<int,char> instead. Since operator < on the pair compares first and decides ties on the second, sorting std::vector<std::pair<int,char>> will produce the exact effect that you want:
vector<pair<int,char>> v;
v.push_back(make_pair(6, 'g'));
v.push_back(make_pair(2, 'r'));
v.push_back(make_pair(3, 'y'));
v.push_back(make_pair(4, 'a'));
sort(v.begin(), v.end());
for (int i = 0 ; i != v.size() ; i++) {
cout << v[i].first << " " << v[i].second << endl;
}
Demo.
You can do something like this:-
vector< pair<int,char> >v;
//do what you want
sort(v.begin(),v.end())
The sort function by default sorts according to first value but you can always define according to which criteria should the sort work
C++ STL - How does the third argument of the STL sort() work?
Try the following.
The way it works is to sort the position key pair based on the int vector value only and then use this ordering to extract values.
#include <iostream>
#include <algorithm>
#include <vector>
class dv
{
std::vector<int> _v1;
std::vector<char> _v2;
std::vector<std::pair<int, int> > _order;
public:
inline bool operator() (const std::pair<int, int>& v1_index_1,
const std::pair<int, int>& v1_index_2) const {
return _v1[v1_index_1.first] < _v1[v1_index_2.first];
}
void sort() {
std::sort(_order.begin(), _order.end(), *this);
}
void add(int value_v1, char value_v2) {
_order.push_back(std::pair<int, int>(_v1.size(), _v2.size()));
_v1.push_back(value_v1);
_v2.push_back(value_v2);
}
void print() {
const auto size(_v1.size());
for (size_t i=0; i<size; ++i) {
std::cout << _v1[_order[i].first]
<< " "
<< _v2[_order[i].second]
<< std::endl;
}
}
};
int main() {
dv dv;
dv.add(6, 'g');
dv.add(2, 'r');
dv.add(3, 'y');
dv.add(4, 'a');
std::cout << "before sort: " << std::endl;
dv.print();
std::cout << "sorting: " << std::endl;
dv.sort();
std::cout << "after sort: " << std::endl;
dv.print();
return 0;
}

Algorithm to efficiently identify duplicate in an array of strings in C++

I have a list/array of IP address as string. I need to identify if there are any duplicates in this array and log an error. The array is about 20 elements big. What is an efficient way to identify a duplicate ?
sort original array
iterate over sorted array, and count different values
create new array with size of (2)
copy values from original to new array, skipping duplicates
pseudo in bash:
[user#linux ~]$ cat 1.txt
1
2
3
66
1
1
66
3
7
7
7
7
26
[user#linux ~]$ cat 1.txt | sort | uniq
1
2
26
3
66
7
[user#linux ~]$ cat 1.txt | sort | uniq | wc -l
7
You can use a map<string, int> to mark used addresses and where an address appeared first:
void check_dups(const std::vector<std::string>& addresses) {
std::map<std::string, int> seen;
for (int i=0,n=addresses.size(); i<n; i++) {
std::map<std::string, int>::iterator it = seen.find(addreses[i]);
if (it == seen.end()) {
// Never used before, mark the position
seen[addresses[i]] = i;
} else {
// Duplicated value, emit a warning
std::cout << "Duplicate address at index " << i <<
" (present already at index " << it->second << ")\n";
}
}
}
here are 3 reasonably efficient ways, from the top of my head:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
// returns a sorted, de-duplicated copy
std::vector<std::string> de_duplicated(std::vector<std::string> vec)
{
std::set<std::string> interim { vec.begin(), vec.end() };
vec.assign(interim.begin(), interim.end());
return vec;
}
// sorts and de-duplicates in place
void de_duplicate(std::vector<std::string>& vec)
{
std::sort(std::begin(vec), std::end(vec));
auto current = std::begin(vec);
do {
auto last = std::end(vec);
current = std::adjacent_find(current, last);
if (current != last) {
auto last_same = std::find_if_not(std::next(current),
last,
[&current](const std::string& s) {
return s == *current;
});
current = vec.erase(std::next(current), last_same);
}
} while(current != std::end(vec));
}
// returns a de-duplicated copy, preserving order
std::vector<std::string> de_duplicated_stable(const std::vector<std::string>& vec)
{
std::set<std::string> index;
std::vector<std::string> result;
for (const auto& s : vec) {
if (index.insert(s).second) {
result.push_back(s);
}
}
return result;
}
using namespace std;
int main() {
std::vector<std::string> addresses { "d", "a", "c", "d", "c", "a", "c", "d" };
cout << "before" << endl;
std::copy(begin(addresses), end(addresses), ostream_iterator<string>(cout, ", "));
cout << endl;
auto deduplicated = de_duplicated(addresses);
cout << endl << "sorted, de-duplicated copy" << endl;
std::copy(begin(deduplicated), end(deduplicated), ostream_iterator<string>(cout, ", "));
cout << endl;
deduplicated = de_duplicated_stable(addresses);
cout << endl << "sorted, stable copy" << endl;
std::copy(begin(deduplicated), end(deduplicated), ostream_iterator<string>(cout, ", "));
cout << endl;
de_duplicate(addresses);
cout << endl << "sorted, de-duplicated in-place" << endl;
std::copy(begin(addresses), end(addresses), ostream_iterator<string>(cout, ", "));
cout << endl;
return 0;
}

Find unique strings in C++, and generate associated lookup vector

A have a vector of strings in c++:
vector<string> myVect = {"A", "A", "A", "B", "B", "A", "C", "C", "foo", "A", "foo"};
How can I convert this to a vector of integers, so that each integer uniquely corresponds to a string in myVect?
i.e. I would like a vector
out = {0, 0, 0, 1, 1, 0, 2, 2, 3, 0, 3}
In addition, I would like a vector of the unique strings, each position corresponding to the number in out:
uniqueStrings = {"A", "B", "C", "foo"}
So far I have the following:
vector<string> uniqueStrings; // stores list of all unique strings
vector<int> out(myVect.size());
for (int i = 0; i < myVect.size(); ++i)
{
// seeing if this string has been encountered before
bool assigned = false;
for (int j = 0; j < uniqueStrings.size(); ++j)
if (!myVect.at(i).compare( uniqueStrings.at(j) ))
{
out.at(i) = j;
assigned = true;
break;
}
// if not, add new example to uniqueStrings
if (!assigned)
{
uniqueStrings.push_back(myVect.at(i));
out.at(i) = uniqueStrings.size();
}
}
This works, but surely there must be a better way?
Keep pushing them in a map where the string is the key and the value corresponds to the id of each string. Then the values of your map will uniquely correspond to the strings and the keys will be the unique strings.
Use a set.
# include <set>
...
set <string> uniqueStrings;
...
for (int i = 0; i < myVect.size(); ++i)
{
uniqueStrings.insert(myVect[i]);
}
Here's a more or less complete example of how you might use a std::map<> to maintain a mapping of unique strings to an integer ID:
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
// a simple functor type that makes it easier to dump the contents of a
// container of simple values or a container of std::pair
struct dump
{
template <typename K, typename V>
void operator()( typename std::pair<K,V> const& x)
{
cout << x.first << " ==> " << x.second << endl;
}
template <typename T>
void operator()( T const& x)
{
cout << x << endl;
}
};
#define NUM_ELEM(x) (sizeof(x)/sizeof(x[0]))
char const* data[] = {"A", "A", "A", "B", "B", "A", "C", "C", "foo", "A", "foo"};
int main() {
// intialize the data set
vector<string> myVect( data, data + NUM_ELEM(data));
cout << "dump of initial data set" << endl << endl;
for_each( myVect.begin(), myVect.end(), dump());
map<string,size_t> uniqueStrings; // stores collection of all unique strings
for (vector<string>::iterator i = myVect.begin(); i != myVect.end(); ++i) {
// I'm using uniqueStrings.size() as a convenience here...
// I just needed something to generate unique ID's easily,
// it might not be appropriate to use size() for your ID's in real life
// this will insert the new mapping if there's not already one
uniqueStrings.insert( make_pair(*i, uniqueStrings.size()));
}
cout << endl << endl<< "dump of uniqueStrings" << endl << endl;
for_each( uniqueStrings.begin(), uniqueStrings.end(), dump());
// I'm not sure if you'd need this `out` vector anymore - you can probably just
// use the `uniqueStrings` map directly for this information (but that would
// depend on your specific needs)
vector<int> out;
for (vector<string>::iterator i = myVect.begin(); i != myVect.end(); ++i) {
out.push_back( uniqueStrings[*i]);
}
cout << endl << endl << "dump of `out` vector" << endl << endl;
for_each( out.begin(), out.end(), dump());
return 0;
}