I have a std::set<vector<int>> from which I would like to move (not copy) elements to a std::vector<vector<int>>. How do I do this?
I tried using move (which I use to move between vectors) with the following piece of code but it won't compile.
#include<iostream>
#include<set>
#include<vector>
using namespace std;
int main(){
set<vector<int>> res;
vector<int> first = {1,2,3};
vector<int> second = {4,5,6};
res.insert(first);
res.insert(second);
vector<vector<int>> ans;
for(auto i : res){
ans.emplace_back(ans.end(),move(i));
}
return 0;
}
A set<T> does not contain Ts; it contains const Ts. As such, you cannot simply move objects out of it.
This is one of reasons why we still may need const_cast sometimes:
for(auto& i : res){
ans.emplace_back(ans.end(),move(const_cast<T&>(i)));
}
No point to do it for int elements though.
Related
I have a std::vector< std::vector< int> > that contains prime numbers. I wish to eliminate double entries, as the vector contents will be exported to a file and should only contain unique primes.
The prime numbers will come from certain intervals, fed to my algorithm through a file, e.g. (32,345). There may be cases where the intervals will overlap e.g. (54,434),(345,596). I wish to use std::unordered_set, since it will be the most efficient for my case.
I have seen examples with a std::vector< int> and tried to accommodate that to my needs, to no avail.
Here is code I tried, inspired by the print method of a 2d vector.
std::vector<std::vector<int> > sharedAnswersVec;
...
...
std::unordered_set<int> unique_primes;
for (auto i = 0; i < sharedAnswerVec.size(); i++)
{
for (auto j = 0; j < sharedAnswerVec[j].size(); j++)
{
unique_primes.insert({ i,j });
sharedAnswerVec.assign(unique_primes.begin(), unique_primes.end());
sort(sharedAnswerVec.begin(), sharedAnswerVec.end());
}
}
sharedAnswerVec cannot be std::vector< int>, has to be std::vector< std::vector< int> >.
With that in mind, what changes must I do in order to correct it?
I am a beginner trying to learn, so if the question seems silly to you, please bear that in mind.
You are trying to insert something into your std::unordered_set<int> something which is not an int.
It is not clear to me what your "intervals" are, or what you are doing when sorting. Perhaps this is some use?
#include <iostream>
#include <vector>
#include <set>
int main()
{
std::vector<std::vector<int> > sharedAnswersVec = {
{1,2,3,5,7,11,13,17,19,23,29},
{2,5,11,17,23,29}
};
std::set<int> unique_primes;
for ( const auto& v : sharedAnswersVec )
{
for ( auto i : v )
{
unique_primes.insert(i);
}
}
for ( auto i : unique_primes )
{
std::cout << i << std::endl;
}
return 0;
}
Is it possible to put the iterator of list in to set:
I wrote codes as follows :
It failed on VS2015 but run smoothly on g++
And I also tried to use std::hash to calculate a hash value of std::list::iterator
but failed again, it has no hash func for iterator.
And one can help ? Or it's impossible .....
#include <set>
#include <list>
#include <cstring>
#include <cassert>
// like std::less
struct myless
{
typedef std::list<int>::iterator first_argument_type;
typedef std::list<int>::iterator second_argument_type;
typedef bool result_type;
bool operator()(const std::list<int>::iterator& x,const std::list<int>::iterator& y) const
{
return memcmp(&x, &y, sizeof(std::list<int>::iterator)) < 0; // using memcmp
}
};
int main()
{
std::list<int> lst = {1,2,3,4,5};
std::set<std::list<int>::iterator,myless> test;
auto it = lst.begin();
test.insert(it++);
test.insert(it++);
assert(test.find(lst.begin()) != test.end()); // fail on vs 2015
auto it1 = lst.end();
auto it2 = lst.end();
assert(memcmp(&it1,&it2,sizeof(it1)) == 0); // fail on vs 2015
system("pause");
return 0;
}
Yes, you can put std::list<T>::iterator in a std::set, if you tell std::set what order they should be in. A reasonable order could be std::less<T>, i.e. you sort the iterators by the values they point to (obviously you then can't insert an std::list::end iterator). Any other order is also OK.
However, you tried to use memcmp, and that is wrong. The predicate used by set requires that equal values compare equal, and there is no guarantee that equal iterators (as defined by list::iterator::operator==) also compare equal using memcmp.
I find a way to do this as like but not for the end iterator
bool operator<(const T& x, const T& y)
{
return &*x < &*y;
}
#include <iostream>
#include <vector>
#include <algorithm>
#include <tuple>
using namespace std;
typedef long long ll;
vector < tuple <ll,ll,ll> > a;
int main()
{
ll t;
cin>>t;
ll id,z,p,l,c,s,newz;
while(t--)
{
cin>>id>>z>>p>>l>>c>>s;
newz=p*50+l*5+c*10+s*20;
a.push_back(make_tuple(z-newz,id,newz));
}
sort(a.begin(),a.end());
for(int i=0;i<5;i++)
{
tie(ignore,id,z)=a[i];
cout<<id<<" "<<z<<endl;
}
return 0;
}
I want the sort on the vector to happen on the basis of first element of the tuple but only when there is a tie then the smallest of the second element of the tuple must be chosen to order the elements with the same first value.
Also specify what should be done, if at the time of a tie the order should be maintain on the basis of greater element of the second element of the tuple(instead of the first).
A custom function as a third parameter sorted my way out perfectly.
bool cmp( tuple <ll,ll,ll> const &s, tuple <ll,ll,ll> const &r)
{
if(get<0>(s)==get<0>(r))
{
return (get<1>(s))>(get<1>(r));
}
else
return (get<0>(s))<(get<0>(r));
}
sort(a.begin(),a.end(),cmp);// Call to sort will change like this.
I have some old C code that still runs very fast. One of the things it does is store the part of an array for which a condition holds (a 'masked' copy)
So the C code is:
int *msk;
int msk_size;
double *ori;
double out[msk_size];
...
for ( int i=0; i<msk_size; i++ )
out[i] = ori[msk[i]];
When I was 'modernising' this code, I figured that there would be a way to do this in C++11 with iterators that don't need to use index counters. But there does not seem to be a shorter way to do this with std::for_each or even std::copy.
Is there a way to write this up more concisely in C++11? Or should I stop looking and leave the old code in?
I think you are looking for std::transfrom.
std::array<int, msk_size> msk;
std::array<double, msk_size> out;
double *ori;
....
std::transform(std::begin(msk), std::end(msk),
std::begin(out),
[&](int i) { return ori[i]; });
In case you only want to modernize the loop, and keep the ori and msk data around, use #YuxiuLi's solution. If you also want to modernize the generation of the msk data, you can use std::copy_if with a predicate (here: a lambda that keeps only the negative numbers) to filter the elements directly.
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>
int main()
{
auto ori = std::vector<double> { 0.1, -1.2, 2.4, 3.4, -7.1 };
std::vector<double> out;
std::copy_if(begin(ori), end(ori), std::back_inserter(out), [&](double d) { return d < 0.0; });
std::copy(begin(out), end(out), std::ostream_iterator<double>(std::cout, ","));
}
Live Example. This saves an intermediate storage of msk.
I was trying to sort a structure using stl sort in C++ . But i get some error . Is it that we cannot sort a structure in c++ using stl sort or is it my fault in implementation , if its my fault do let me know the correction .
Here's the code (its very small :) )
#include<iostream>
#include<algorithm>
using namespace std;
struct log {
int sd;
int ed;
} log[1000];
bool key(int i,int j) {
return (log[i].ed<log[j].ed);
}
int main() {
int n,i;
cin>>n;
sort(log,log+n,key);
for (i=0;i<n;i++) cin>>log[i].sd>>log[i].ed;
for (i=0;i<n;i++) cout<<log.sd<<","<<log.ed<<endl;
system("PAUSE");
}
Yes, you can. But your comparator should take two const log & (not int) arguments.