what is the alternative to set_difference in c++ - c++

I have two sets.they have some common elements(sets have strings as thier elements)
like :
set1 has elements
"1-2","1-1","3-4"
set2 has elements
"1-2","1-3","3-4"
i want take out the values "1-1" into one set
and value "1-3" into another.
i know set_difference will do the job for me.But some how i am facing some problems with set_ifference.please check here
Is there any alternative to using set_difference achieving the same reults?

The alternative would be to roll your own, as Kerrek SB did in his answer to your question.
That said, it would be far better to understand and to solve the problem you have with std::set_difference(), rather than working around it.
For instance, were I getting long compiler errors involving templates on the line containing set_difference, I would break this up into a small series of separate, simple statements, which will make pinpointing the error much easier:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <set>
#include <string>
int main()
{
typedef std::set<std::string> set_of_strings;
set_of_strings s1, s2, result;
s1.insert("1-2");
s1.insert("1-1");
s1.insert("3-4");
s2.insert("1-2");
s2.insert("1-3");
s2.insert("3-4");
// Temporary variables for debugging only
set_of_strings::iterator s1_begin = s1.begin();
set_of_strings::iterator s1_end = s1.end();
set_of_strings::iterator s2_begin = s2.begin();
set_of_strings::iterator s2_end = s2.end();
set_of_strings::iterator result_end = result.end();
std::insert_iterator<set_of_strings> result_inserter = std::inserter(result, result_end);
std::set_difference(s1_begin, s1_end,
s2_begin, s2_end,
result_inserter);
std::copy(result.begin(),
result.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
}
The compiler would then check that each of set_difference's five parameters is of the type that it expects and would allow me to see quite quickly which of them is causing the issue because they're all declared in separate statements.
Once I'd solved the issue, I'd refactor to remove the unnecessary variables, of course.

Related

Comparing unordered_map vs unordered_set

First of all, what is the main difference between them?
The only thing i've found is that unordered_set has no operator [].
How should i access an element in unordered_set, since there is no []?
Which container is using random access to memory(or both)?
And which one of them faster in any sense or using less memory?
They are nearly identical. unordered_set only contains keys, and no values. There is no mapping from a key to a value, so no need for an operator[]. unordered_map maps a key to a value.
You can use the various find methods within unordered_set to locate things.
you can use iterators to access elements.
unordered_set <string> u{
"Dog",
"Cat",
"Rat",
"Parrot",
"bee"
};
for(auto& s:u){
cout << s << ' ';
}
unordered_set<string>::const_iterator point = u.find("bee");
How should I access an element in unordered_set (C++17)?
In C++ 17 a new function extract is added to unordered_set.
Specially, this is the only way to take move only object out of the set.
https://en.cppreference.com/w/cpp/container/unordered_set/extract
For example if you want third element of your unordered set.
Advance the iterator
std::advance(it,2);
Then extarct the value
s.extract(it).value();
Here is the complete code. try on any C++17 compiler.
#include <iostream>
#include <string>
#include <unordered_set>
#include <iterator>
int main()
{
//CREATE AN OBJECT
std::unordered_set<std::string> s;
//INSERT DATA
s.insert("aee");
s.insert("bee");
s.insert("cee");
s.insert("dee");
//NEED TO INCLUDE "iterator" HEADER TO USE "std::advance"
auto it = s.begin();
std::advance(it,2);
//USING EXTRACT
std::string sval = s.extract(it).value();
std::cout<<sval;
}
Note: if queried for out of bound index, nothing happens. No result.
Try changing your code
//ONLY FOUR ELEMENTS
std::advance(it,8);
//USING EXTRACT
std::string sval = s.extract(it).value();

Replace 'for loop' using std::for_each

I have a for loop in the below code and I would like to implement it using std::for_each. I have implemented it. Could someone please tell me if that is the best way to do it using std::for_each? If not, could you please suggest the right one?
#include <vector>
#include <cstdint>
#include <string>
#include <algorithm>
#include <iostream>
#include <sstream>
int main()
{
std::vector<std::uint32_t> nums{3, 4, 2, 8, 15};
std::stringstream list1;
for (auto n : nums)
{
list1 << n<<",";
}
//Is this the right way to do using std::for_each so that above for loop can be done in 1 line??
std::for_each(nums.begin(),nums.end(),[&list1](std::uint32_t n){ list1 << n << ","; });
}
Yes, your use of for_each is a reasonable analog of the preceding loop.
I feel obliged to point out, however, that I find for_each probably the least useful algorithm in the library. From what I've seen, using it generally indicates that you're still basically thinking in terms of loops, and just changing the syntax you use for those loops. I also think that range-based for loops have probably eliminated at least 90% of the (already few) legitimate uses there used to be for for_each.
In this case, your code is really imitating using std::copy with an std::ostream_iterator:
std::copy(nums.begin(), nums.end(),
std::ostream_iterator<std::uint32_t>(std::cout, ","));
Even this, however, is clumsy enough that I think it's open to question whether it's really an improvement over a range-based for loop.
Why don't you just test it out?
auto vs std::for_each
As you can see the assembly output is the same for both. It just doesn't make any difference for your example.
If you want to copy the data from one thing to another you can use std::copy
int main()
{
std::vector<std::uint32_t> nums{3, 4, 2, 8, 15};
std::stringstream list1;
std::copy(nums.begin(), nums.end(),std::ostream_iterator<std::uint32_t>(list1,","));
std::cout << list1.str();
}
Live Example
This will end the stream with a , but that is the same thing you get in you code.
If you do not want this then you should look at Pretty-print C++ STL containers
Yes, that is right. There is no need for the reference in (std::uint32_t &n) if you had performance as the motive.

Is it possible to iterate over an iterator?

I have a working program that capitalizes strings in a vector, using iterators:
vector<string> v7{ 10, "apples" };
for (auto vIterator= v7.begin(); vIterator!= v7.end(); ++vIterator){
auto word = *vIterator; //here
auto charIterator = word.begin();
*charIterator = toupper(*charIterator);
*vIterator = word; //also here, i guess i could just print `word` instead?
cout << *vIterator << endl;
}
My question is;
2nd line inside the loop # the comment, i had to save the pointer to the iterator to another string variable before i was able to iterate over it.
Iterating over the pointer like so
*vIterator.begin();
didn't seem to work.
Is this the correct practice, or am i missing something?
I'm new to the C languages, the concept behind pointer-like tools is quite hard to understand even if i can use them, and in this case it just feels like I'm doing it wrong.
Edit: It was a syntax error (*vIterator).begin();
It just didn't make sense why i'd have to save it to another variable before iterating over it, cheers.
Since you are using C++11 look how simpler your code can become using ranged loops like the example below:
std::vector<std::string> v(10, "apples");
for(auto &&word : v) {
word[0] = toupper(word[0]);
}
LIVE DEMO
Now as far as it concerns the (*vIterator.begin(); didn't seem to work.):
The dot operator (i.e., .) has a higher precedence than the dereference operator (i.e., *). Thus, *vIterator.begin() is interpreted as *(vIterator.begin()). The compiler rightfully complains because vIterator hasn't got a member begin().
Think of iterators as if they were pointers. The correct way to access the members of an object via a pointer/iterator pointing to it is either using the arrow operator (i.e., vIterator->begin()) or first dereference the pointer/iterator and then use the dot operator (i.e., (*vIterator).begin()).
So your code via the use of iterators would become:
std::vector<std::string> v(10, "apples");
for(auto it(v.begin()), ite(v.end()); it != ite; ++it) {
*(it->begin()) = toupper(*(it->begin()));
}
LIVE DEMO
The correct way to write *vIterator.begin(); is (*vIterator).begin(); or, more often, vIterator->begin();. Also note that you can also access the first character of a string directly (without having to iterate over it) as word[0].
A simple STL-ish way of doing it:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<string> v7{ 10, "apples" };
for_each(v7.begin(), v7.end(), [](string& word){word[0] = toupper(word[0]);});
}

Producing permutations of a set of integers in C++. Getting Segmentation Fault

I was trying to solve a problem which involved producing all the permutations of a set of numbers. The idea seemed simple enough (code below), but I keep getting segmentation faults. Can anyone tell me what I'm doing wrong?
void permute(set<int>& s, vector<int>& v) {
if(s.empty()) {
// read the permutation in v.
return;
}
set<int>::iterator i;
for(i = s.begin(); i != s.end(); i++) {
int x = *i;
s.erase(i);
v.push_back(x);
permute(s, v);
v.pop_back();
s.insert(x);
}
}
To produce all permutations in C++ use std::next_permutation. The problem here is that you cannot permutate the set, because the ordering is preset by the key comparator operator (in your case the less than operator). What you can do is store your values in a non associative container and then have a go.
#include <set>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
void permut(std::set<int> const &inp, std::vector<int> &all_permutations)
{
vector<int> tmp(inp.size());
copy(inp.begin(), inp.end(), tmp.begin());
vector<int> all_permutations;
do
{
copy(tmp.begin(), tmp.end(), back_inserter(all_permutations));
} while (std::next_permutation(tmp.begin(), tmp.end()));
}
The permute() function calls itself recursively while iterating over the mutable containers and making changes. This violates iterator validity promises.
You might try something based on std::next_permutation()
I have not gone into the precise behaviour you can expect from a set, but it seems pretty clear that the things you are doing inside the for loop are enough to make the iterator invalid. I would suggest redesigning things so that you have two sets, and work through one (which starts off full) while generating the permutation in the other (which starts off empty).

C++ to compare 2 lists of strings

In Python, set is pretty handy for comparing 2 lists of strings (see this link). I was wondering if there's a good solution for C++ in terms of performance. As each list has over 1 million strings in it.
It's case-sensitive matching.
The data types std::set<> (usually implemented as a balanced tree) and std::unordered_set<> (from C++11, implemented as a hash) are available. There is also a convenience algorithm called std::set_intersection that computes the actual intersection.
Here is an example.
#include <iostream>
#include <vector>
#include <string>
#include <set> // for std::set
#include <algorithm> // for std::set_intersection
int main()
{
std::set<std::string> s1 { "red", "green", "blue" };
std::set<std::string> s2 { "black", "blue", "white", "green" };
/* Collecting the results in a vector. The vector may grow quite
large -- it may be more efficient to print the elements directly. */
std::vector<std::string> s_both {};
std::set_intersection(s1.begin(),s1.end(),
s2.begin(),s2.end(),
std::back_inserter(s_both));
/* Printing the elements collected by the vector, just to show that
the result is correct. */
for (const std::string &s : s_both)
std::cout << s << ' ';
std::cout << std::endl;
return 0;
}
Note. If you want to use std::unordered_set<>, the std::set_intersection cannot be used like this, because it expects the input sets to be ordered. You'd have to use the usual technique of a for-loop iterating over the smaller set and finding the elements in the larger one to determine the intersection. Nevertheless, for a large number of elements (especially, strings), the hash-based std::unordered_set<> may be faster. There are also STL-compatible implementations such as the one in Boost (boost::unordered_set) and the one created by Google (sparse_hash_set and dense_hash_set). For various other implementations and benchmarks (including one for strings), see here.
If you don't need much performance I suggest using map/set from STL:
list<string> list, list2;
...
set<string> sndList;
list<string> result;
for(list<string>::iterator it = list2.begin(); it != list2.end(); ++it)
sndList.insert(*it);
for(list<string>::iteratir it = list.begin(); it != list.end(); ++it)
if(sndList.count(*it) > 0)
result.push_back(*it);
Otherwise I suggest some hashing function for comparison.
If it really is a std::list you have, sort them and use set_intersection:
list<string> words1;
list<string> words2;
list<string> common_words;
words1.sort();
words2.sort();
set_intersection(words1.begin(), words1.end(),
words2.begin(), words2.end(),
back_inserter(common_words));