How to compare multiple QStrings at once? - c++

In qt there's another way to compare multiple strings than writing many str1 == str2 || ...
QString a = "red";
QString b = "yellow";
QString c = "blue";
QString d = "green";
QString e = "gray";
if (a == b || a == c || a == d || a == e)
{
}

One simple approach is to create a container with all of allowable strings and use its find function to see if it's in the container. Depending on the container you select it may not have it's own find function. In that case you can still rely on std::find to simply find the string.
The following example uses a std::set to store all the valid strings you want to find and uses its find member function to handle the searching without doing any additional checks for strings you may want to ignore.
#include <set>
#include <vector>
#include <iostream>
int main()
{
std::set<QString> validLabels{ "yellow", "blue", "green", "gray" };
std::vector<QString> needles{ "red", "yellow", "blue", "green", "gray" };
for (const auto& needle : needles)
{
if (validLabels.find(needle) != validLabels.end())
{
std::cout << "Found " << needle << "\n";
}
else
{
std::cout << "Did not find " << needle << "\n";
}
}
}
The following example uses a std::vector to store all allowable strings and uses std::find to find the string.
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<QString> validLabels{ "yellow", "blue", "green", "gray" };
std::vector<QString> needles{ "red", "yellow", "blue", "green", "gray" };
for (const auto& needle : needles)
{
if (std::find(validLabels.begin(), validLabels.end(), needle) != validLabels.end())
{
std::cout << "Found " << needle << "\n";
}
else
{
std::cout << "Did not find " << needle << "\n";
}
}
}
Both examples generate the following output
Did not find red
Found yellow
Found blue
Found green
Found gray

Related

How to compare two text files and find the similarities between then?

i have loaded both of my files into an array and im trying to compare both of the files to get the comparisons inside the file. However when I run my code I don't receive an output.
This is the contents of both files.
file1
tdogicatzhpigu
file2
dog
pig
cat
rat
fox
cow
So when it does a comparison between the words from search1.txt and the words from text1.txt. I want to find the occurence of each word from search1.txt in text1.txt
What I want to eventually output is whether it has been found the index of the location inside the array.
e.g
"dog". Found, location 1.
Here is my code
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream file1("text1.txt");
if (file1.is_open())
{
string myArray[1];
for (int i = 0; i < 1; i++)
{
file1 >> myArray[i];
any further help would be greatly appreciated. Thanks in advance.
I believe the goal is to search the text in file1 for each word in file2.
You can't use equality for the two strings, as they aren't equal. You'll need to use the std::string::find method:
std::string target_string;
std::getline(file1, target_string);
std::string keyword;
while (getline(file2, keyword))
{
const std::string::size_type position = target_string.find(keyword);
std::cout << "string " << keyword << " ";
if (position == std::string::npos)
{
std::cout << "not found.\n";
}
else
{
std::cout << "found at position " << position << "\n";
}
}
Edit 1:
An implemented example:
#include <iostream>
#include <string>
using std::cout;
using std::string;
using std::endl;
int main()
{
const std::string target_string = "tdogicatzhpigu";
const std::string key_list[] =
{
"dog",
"pig",
"cat",
"rat",
"fox",
"cow",
};
static const unsigned int key_quantity =
sizeof(key_list) / sizeof(key_list[0]);
for (unsigned int i = 0; i < key_quantity; ++i)
{
const std::string::size_type position = target_string.find(key_list[i]);
std::cout << "string " << key_list[i] << " ";
if (position == std::string::npos)
{
std::cout << "not found.\n";
}
else
{
std::cout << "found at position " << position << "\n";
}
}
return 0;
}

Efficient way to get key from value when map contain vector of string as value

How to get key using value which is vector of string and vice versa. Below is my code.
#include<iostream>
#include<map>
#include<string>
#include <unordered_map>
#include <vector>
using namespace std;
int main()
{
std::unordered_map<std::string, std::vector<std::string>> Mymap;
Mymap["unique1"] = {"hello", "world"};
Mymap["unique2"] = {"goodbye", "goodmorning", "world"};
Mymap["unique3"] = {"sun", "mon", "tue"};
for(auto && pair : Mymap) {
for(auto && value : pair.second) {
std::cout << pair.first<<" " << value<<"\n";
if(value == "goodmorning") // how get key i.e unique2 ?
}}
}
case 1: When value is input. key is output.
Input : goodmorning
output : unique2
case 2: When key is input value is output.
Input : unique3
output: sun ,mon ,tue
Note : No boost library available.
For case 1, a combination of find_if and any_of will do the job.
For case 2, you can simply use the find method of unordered_map.
#include<iostream>
#include<map>
#include<string>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
unordered_map<string, vector<string>> Mymap;
Mymap["unique1"] = { "hello", "world" };
Mymap["unique2"] = { "goodbye", "goodmorning", "world" };
Mymap["unique3"] = { "sun", "mon", "tue" };
// Case 1
string test_value = "goodmorning";
auto iter1 = find_if(Mymap.begin(), Mymap.end(),
[&test_value](const decltype(*Mymap.begin()) &pair)
{
return any_of(pair.second.begin(), pair.second.end(), [&test_value](const string& str) { return str == test_value; });
});
if (iter1 != Mymap.end())
{
cout << "Key: " << iter1->first << endl;
}
else
{
cout << "No key found for " << test_value;
}
// Case 2
test_value = "unique3";
auto iter2 = Mymap.find(test_value);
if (iter2 != Mymap.end())
{
int first = true;
for (auto v : iter2->second)
{
cout << (first ? "" : ", ") << v;
first = false;
}
cout << endl;
}
else
{
cout << "No value found for key " << test_value << endl;
}
return 0;
}
The key is stored in pair.first. Just use that if your use-case is in loop iteration as you illustrated.
If you mean in any use, without iteration, that is, given a value obtain the associated key, there is not a direct way to do that. You could build inverse maps for each value to key but that would not be really efficient considering also the fact that you would also need unique values.
Create another map going the other way for every vector entry?
If the array entries are not unique, then you would need to do the same map-to-vector, or use multimap.
Also consider using hash map (unordered_map), and stringview as ways to reduce the memory usage of the second map?
But the best answer would be the boost 2-way map, sorry. You could wrap the two maps in your own class that exposes the functionality of a 2-way map.

Sorting JSON values alphabetically C++

If my json file is this:
[
{
"friendName": "Ann",
"birthday": "1990-04-19",
"favoriteColor": "Purple",
},
{
"friendName": "Rachel",
"birthday": "1995-7-05",
"favoriteColor": "Pink",
},
{
"friendName": "Max",
"birthday": "1993-10-07",
"favoriteColor": "Purple",
},
{
"friendName": "Bob",
"birthday": "1992-02-20",
"favoriteColor": "Red",
}
]
How could I obtain the youngest girl's name? (As in sorting the girls' birthday strings in descending order, then grabbing the first object in the list (1993-10-07) and printing their name).
I am using JSON for Modern C++ (https://github.com/nlohmann/json) and Xcode (version 6).
In my project, I will not know the amount of objects I will have. Is there a way to sort these strings by comparison?
A nice thing about the nlohmann/json is that it offers STL-like access, which allows for using a nlohmann::json with most of the functions in <algorithm>.
In particular, std::min_element() might come in handy when looking for the min element in a container... given a custom comparison function :)
In the following code, I used the dob_comp() lambda as a comparison function to compare persons by their dates of birth (dob). The youngest person is, therefore, the one with the "minimum date of birth".
[run it online (close main.cpp if it's open, click compile, then execute)]
// compile with: g++ --std=c++11 this_file.cpp -o your_executable_name
#include <algorithm>
#include <ctime>
#include <iomanip>
#include <iostream>
#include "json.hpp"
int main()
{
// sample json object
nlohmann::json j = nlohmann::json::parse("["
"{"
" \"friendName\": \"Ann\","
" \"birthday\": \"1990-04-19\","
" \"favoriteColor\": \"Purple\""
"},"
"{"
" \"friendName\": \"Rachel\","
" \"birthday\": \"1995-07-05\","
" \"favoriteColor\": \"Pink\""
"},"
"{"
" \"friendName\": \"Max\","
" \"birthday\": \"1993-10-07\","
" \"favoriteColor\": \"Purple\""
"},"
"{"
" \"friendName\": \"Bob\","
" \"birthday\": \"1992-02-20\","
" \"favoriteColor\": \"Red\""
"}"
"]");
// converts a date string to a std::tm structure
// assumes the string is formatted as "YYYY-MM-DD"
const auto str_to_time = [] (std::string str) {
std::tm tm;
// http://stackoverflow.com/a/21021900
//std::stringstream ss(str);
//ss >> std::get_time(&tm, "%Y-%m-%d");
strptime(str.c_str(), "%Y-%m-%d", &tm);
return tm;
};
// simplistic comparison of std::tm structures -- compares only the (year,month,day)
const auto time_comp = [] (const std::tm& t1, const std::tm& t2) {
if (t1.tm_year < t2.tm_year)
{
return true;
}
else if (t1.tm_year > t2.tm_year)
{
return false;
}
else if (t1.tm_mon < t2.tm_mon)
{
return true;
}
else if (t1.tm_mon > t2.tm_mon)
{
return false;
}
else if (t1.tm_mday < t2.tm_mday)
{
return true;
}
else if (t1.tm_mday > t2.tm_mday)
{
return false;
}
else
{
return true;
}
};
// I didn't have time to read too much of the "json.hpp" header
// so I used a quick "decltype()" to find the iterator type
using json_iterator_type = decltype(*j.begin());
// compares the DatesOfBirth (dob) of two persons
const auto dob_comp = [&str_to_time, &time_comp] (const json_iterator_type p1, const json_iterator_type p2) {
std::string dob1 = p1["birthday"];
std::string dob2 = p2["birthday"];
auto ttm1 = str_to_time(dob1);
auto ttm2 = str_to_time(dob2);
return time_comp(ttm1, ttm2);
};
// know your <algorithm>'s :)
const auto youngest = *std::min_element(j.begin(), j.end(), dob_comp);
std::cout << "The youngest person is: " << youngest << std::endl;
}
Note: if you want to sort the elements, you can use std::sort() like this:
std::sort(j.begin(), j.end(), dob_comp);
Note2: check out jq if you need a tool for processing json files.

Compare two strings in C++

I want to compare user input with the values stored in an string array. My array is
string colours[] = {"Black","Blue","Green","Orange","Red","Yellow"};
User input is assign to
CString selectedColor;
How can I compare these values?
What I would do:
#include <iostream>
int main(void)
{
std::string colours[] = {"Black","Blue","Green","Orange","Red","Yellow"};
std::string input;
std::cin >> input;
for(const auto& color : colours) //c++11 loop, you can use a regular loop too
{
if(input == color)
{
std::cout << input << " is a color!" << std::endl;
}
}
}
You could also convert the CString to a std::string and compare them or the other way around convert the std::string to CString and compare but this has been asked and answered already: How to convert CString and ::std::string ::std::wstring to each other?
Another possible solution, already with all conversions:
std::string colours[] = { "Black", "Blue", "Green", "Orange", "Red", "Yellow" };
CString selectedColor("Blue");
int colours_size = sizeof(colours) / sizeof(colours[0]);
for (int i = 0; i < colours_size; ++i) {
CString comparedColor(colours[i].c_str());
if (selectedColor.Compare(comparedColor) == 0) {
std::cout << "Color found" << std::endl;
}
}

Similar splice in C++ like the splice in Javascript?

is there a similar method/function in C++ like the splice in Javascript?
Example from W3School:
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2,1,"Lemon","Kiwi");
The result of fruits will be:
Banana,Orange,Lemon,Kiwi,Mango
I wan't to be able to do the same thing in C++. I have created an array of boxes that should dissapear one by one when I click on them. I don't know how to do it, please help.
PS. I'm using the SDL library and Microsoft Visual C++ 2010 Express.
If you're using a vector, you have access to the insert method:
#include <vector>
#include <iostream>
#include <string>
int main()
{
std::vector<std::string> fruits = {"Banana", "Orange", "Apple", "Mango"};
auto pos = fruits.begin() + 2;
fruits.insert(pos, {"Lemon", "Kiwi"});
for (auto fruit : fruits) std::cout << fruit << " ";
}
Output: Banana Orange Lemon Kiwi Apple Mango
Here is a Demo.
In C++11:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template<typename T>
vector<T> splice(vector<T>& v, int start, int howmuch, const vector<T>& ar) {
vector<T> result(begin(v) + start, begin(v) + start + howmuch);
v.erase(begin(v) + start, begin(v) + start + howmuch);
v.insert(begin(v) + start, begin(ar), end(ar));
return result;
}
int main() {
vector<string> fruits = {"Banana", "Orange", "Apple", "Mango"};
auto v = splice(fruits, 2, 1, {"Lemon", "Kiwi"});
cout << "Returned value: " << endl;
for (auto &s: v) {
cout << "\t" << s << endl;
}
cout << endl;
cout << "fruits: " << endl;
for (auto &s: fruits) {
cout << "\t" << s << endl;
}
}
Produces the output:
Returned value:
Apple
fruits:
Banana
Orange
Lemon
Kiwi
Mango
It's a templated version so it should work not only with strings;
Function behaves the same as JS version but you have to pass your vector as the first parameter here.