how to access set elements by index like vector? - c++

I have made a code that construct a set of sets. However, I want to access set index like vector *(vec.begin()+i) .Is it possible like accessing vector? I got an error,Please help me, Is there any solution
#include <iostream>
#include <set>
using namespace std;
int main ()
{
int myints[] = {75,23,65,42,13};
std::set<int> myset (myints,myints+5);
std::cout << "myset contains:";
for (int i = 0; i < myset.size(); i++) {
cout<<*(myset.begin()+i);
}
std::cout << '\n';
return 0;
}

You can with std::next. But it's not a good idea for std::set because it must linearly increment the iterator.
auto third = std::next(myset.begin(), 2);

Related

iterate over vector of unrodered set

I'm still learning c++ and do not understand one thing that I encountered today.
I see that an adjacency_list_ if defined by
std::vector<std::unordered_set<int> > bla::blaa::adjacency_list_
I believe that it is an vector of unordered set.
I want to know:
What is this data-structure, vector of unordered set?
How can I traverse it to get the adjacency list, please provide a general MWE for traversal of such data-structures?
Thanks in advance for teaching me this new thing.
A minimum (not) working example:
#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;
int main()
{
vector<unordered_set<int> > my_sets;
for (int i=0; i<5; i++){
my_sets[i].insert(i*2);
}
for(int i=0;i<my_sets.size();i++)
{
for(unordered_set<int> :: iterator it = my_sets[i].begin(); it != my_sets[i].end();++it)
{
cout << *it;
}
}
return 0;
}
You have a problem in your code, your vector is empty, yet you're trying to access indices from 0 to 4. you should set the size of the vector first before iterating. Also you can use range based for loop to avoid writing alot of boilerplate code.
This code is correct and I think it does what you want:
#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;
int main()
{
vector<unordered_set<int>> my_sets(5);
// ^^^
// number 5 here initializes the vector with the size of 5
for (int i = 0; i < 5; i++)
my_sets[i].insert(i*2);
for (auto &my_set : my_sets)
for (auto num : my_set)
cout << num;
return 0;
}
output:
02468
An adjacency list
is a collection of unordered lists. Each list describes the set of neighbors.
Translating into C++:
std::vector<std::unordered_set<int> > adjlist;
The collection (vector) of a set of neighbours (unordered_set).
Traversing depends on what you want to achieve.
If it is just visiting each node, this can be as simple as
for (int node = 0; node < adjlist.size(); ++node) {
// do something with node
}
or
for (auto &neighbours : adjlist) {
// do something with each node's neighbours
}
If you want to navigate from one node to another node, you must look at the neighbours of a node
std::vector<std::unordered_set<int> > adjlist = {{2, 5}, {2, 3}, {0, 1}, {1, 4}, {3}, {0}};
for (int i = 0; i < adjlist.size(); ++i) {
auto &neighbours = adjlist[i];
for (auto n : neighbours) {
std::cout << i << "->" << n << '\n';
}
}
Since each neighbour points back to each other, this poses the problem of loops and keeping track of already visited nodes.

merging a collection of `Eigen::VectorXd`s into one large `Eigen::VectorXd`

If you go to this Eigen page, you'll see you can initialize VectorXd objects with the << operator. You can also dump a few vector objects into one big VectorXd object (e.g. look at the third example in the section called "The comma initializer").
I want to dump a few vectors into a big vector, but I'm having a hard time writing code that will work for an arbitrarily sized collection of vectors. The following doesn't work, and I'm having a hard time writing it in a way that does (that isn't a double for loop). Any suggestions?
#include <iostream>
#include <Eigen/Dense>
#include <vector>
int main(int argc, char **argv)
{
// make some random VectorXds
std::vector<Eigen::VectorXd> vOfV;
Eigen::VectorXd first(3);
Eigen::VectorXd second(4);
first << 1,2,3;
second << 4,5,6,7;
vOfV.push_back(first);
vOfV.push_back(second);
// here is the problem
Eigen::VectorXd flattened(7);
for(int i = 0; i < vOfV.size(); ++i)
flattened << vOfV[i];
//shows that this doesn't work
for(int i = 0; i < 7; ++i)
std::cout << flattened(i) << "\n";
return 0;
}
The comma initializer does not work like that. You have to fully initialize the matrix from that. Instead, allocate a large enough vector and iterate and assign the blocks.
#include <iostream>
#include <vector>
#include <Eigen/Dense>
// http://eigen.tuxfamily.org/dox/group__TopicStlContainers.html
#include <Eigen/StdVector>
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::VectorXd)
int main()
{
// make some random VectorXds
std::vector<Eigen::VectorXd> vOfV;
Eigen::VectorXd first(3);
Eigen::VectorXd second(4);
first << 1,2,3;
second << 4,5,6,7;
vOfV.push_back(first);
vOfV.push_back(second);
int len = 0;
for (auto const &v : vOfV)
len += v.size();
Eigen::VectorXd flattened(len);
int offset = 0;
for (auto const &v : vOfV)
{
flattened.middleRows(offset,v.size()) = v;
offset += v.size();
}
std::cout << flattened << "\n";
}

How do you use a vector in c++?

I am a beginner in c++ and I am trying to understand vectors.
I know the basic format which is:
vector <dataType> vectorName;
People are telling me that vectors are like arrays. But, what I don't
understand is that for arrays you can do this:
array[] = {1, 2, 3}
But for vectors you don't seem to get to set it to a list. Or do you have
to keep using .push_back().
Also, can you use something like vectorName[1] or not?
Can anyone explain this to me?
Thanks.
You can use the style if you use C++11 or later.
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> vec = {1, 2, 3};
std::cout << vec[1] << std::endl;
return 0;
}
The whole purpose of vectors is to be "infinite", so you don't have to redefine it everytime you need to expand it.
push_back is made so you can add/expand to the array without redefining it; you still access and modify like a normal array:
std::vector<int> a;
a.push_back(2);
a.push_back(6);
std::cout << a[0] << std::end; //2
std::cout << a[1] << std::end; //6
a[0] = 5;
a[1] = 7;
std::cout << a[0] << std::end; //5
std::cout << a[1] << std::end; //7
You can also initialize it old-school style (the = is optional):
std::vector<int> a {2, 6};
std::cout << a[0] << std::end; //2
std::cout << a[1] << std::end; //6
Try this for C++:
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> vec { 34,23 };
return 0;
}
Or even:
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> v(2);
v = { 34,23 };
return 0;
}
seems non of the above gave you any hint on dealing with the vector after you created it, so, let's say you created it with few initial values.
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> vec { 34,23 };
// use push_back(some_value) if you have multiple values to put inside, say 1000.
// instead of using the index [] brackets, try .at() method
std::cout << vec.at(1) << std::endl;
// use both the .size() or the new syntax to loop over it
for (unsigned i = 0 ; i < vec.size() ; i++){
std::cout << vec.at(i) << std::endl;
}
// or the new syntax
for (auto & i : vec){
std::cout << i << std::endl;
}
return 0;
}
Have fun :)
Vectors are expandable arrays. Unlike an array, you are not restricted to the size you initialized it with.
Growth of vector: the vector doubles it size whenever you overflow it. Underneath the hood its still an array but the "expandable" property of it comes by copying the contents of the previous array into a new larger array.
Few things that you can do with vectors in C++
Initialization of vector
vector<Type> one (size, defaultValue);
vector<Type> two (one); // makes a new vector *two* with the contents of *one*
vector<int> three {1,2,3}; // using initializer list
Accessing an element
int temp = three[2]; //array like syntax
int temp = three.at(2);
You cannot increase the size of a vector using this syntax i.e. you cannot dothree[3]=4;
Expanding
three.pusk_back(4);
Shrinking
three.pop_back();

String vector's sort compare and delete

In C++ I have
vector < vector <string> > Kblist;
Inside Kblist, there are many clause, and numbers of clauses=kblist.size(); and every clause in side Kblist is a string-type vector, and every word in sentence is split inside Kblist[i].
What is the fastest way to find the sentence in same words like one in "I love you" and the other in "you love i" and delete these two sentence from Kblist, My code might be work run, but I think it is too slow because of to many circulate. So I wonder is there any better solution which is fast like using sort, clause1==clause2 or other approach.
for (int a=0; a<KBlist.size(); a++){
for (int b=a+1; b<KBlist.size(); b++){
int checksize=0;
if (KBlist[a].size()==KBlist[b].size()) {
for (int c=0; c<KBlist[a].size(); c++){
for (int d=0; d<KBlist[b].size(); d++){
if (KBlist[a][b]==KBlist[c][d]&&KBlist[a][b+1]==KBlist[c][d]) {
checksize=checksize+1;
break;
}
}
}
if (checksize==c.size()) {
inset=1;
break;
}
}
}
}
}while (duplicate==0);
You could iterate over each std::vector and use the algorithms of the standard-library.
There is std::find
// find example
#include <iostream> // std::cout
#include <algorithm> // std::find
#include <vector> // std::vector
int main () {
int myints[] = { 10, 20, 30 ,40 };
int * p;
// pointer to array element:
p = std::find (myints,myints+4,30);
++p;
std::cout << "The element following 30 is " << *p << '\n';
std::vector<int> myvector (myints,myints+4);
std::vector<int>::iterator it;
// iterator to vector element:
it = find (myvector.begin(), myvector.end(), 30);
++it;
std::cout << "The element following 30 is " << *it << '\n';
return 0;
}
there is std::find_if
// find_if example
#include <iostream> // std::cout
#include <algorithm> // std::find_if
#include <vector> // std::vector
bool IsOdd (int i) {
return ((i%2)==1);
}
int main () {
std::vector<int> myvector;
myvector.push_back(10);
myvector.push_back(25);
myvector.push_back(40);
myvector.push_back(55);
std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
std::cout << "The first odd value is " << *it << '\n';
return 0;
}
As you are working with std::string this shouldn't be a large problem.
In your scenario it is probably better to use std::multiset< vector <string> > with comparator that compares std::vector<string> in a way you need it to. This will give you sorted container with duplicated values next to each other and cheap insert/erase.

boost zip_iterator and std::sort

I have two arrays values and keys both of the same length.
I want to sort-by-key the values array using the keys array as keys.
I have been told the boost's zip iterator is just the right tool for locking two arrays together and doing stuff to them at the same time.
Here is my attempt at using the boost::zip_iterator to solve sorting problem which fails to compile with gcc. Can someone help me fix this code?
The problem lies in the line
std::sort ( boost::make_zip_iterator( keys, values ), boost::make_zip_iterator( keys+N , values+N ));
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
int main(int argc, char *argv[])
{
int N=10;
int keys[N];
double values[N];
int M=100;
//Create the vectors.
for (int i = 0; i < N; ++i)
{
keys[i] = rand()%M;
values[i] = 1.0*rand()/RAND_MAX;
}
//Now we use the boost zip iterator to zip the two vectors and sort them "simulatneously"
//I want to sort-by-key the keys and values arrays
std::sort ( boost::make_zip_iterator( keys, values ),
boost::make_zip_iterator( keys+N , values+N )
);
//The values array and the corresponding keys in ascending order.
for (int i = 0; i < N; ++i)
{
std::cout << keys[i] << "\t" << values[i] << std::endl;
}
return 0;
}
NOTE:Error message on compilation
g++ -g -Wall boost_test.cpp
boost_test.cpp: In function ‘int main(int, char**)’:
boost_test.cpp:37:56: error: no matching function for call to ‘make_zip_iterator(int [(((unsigned int)(((int)N) + -0x00000000000000001)) + 1)], double [(((unsigned int)(((int)N) + -0x00000000000000001)) + 1)])’
boost_test.cpp:38:64: error: no matching function for call to ‘make_zip_iterator(int*, double*)’
You can't sort a pair of zip_iterators.
Firstly, make_zip_iterator takes a tuple of iterators as input, so you could call:
boost::make_zip_iterator(boost::make_tuple( ... ))
but that won't compile either, because keys and keys+N doesn't have the same type. We need to force keys to become a pointer:
std::sort(boost::make_zip_iterator(boost::make_tuple(+keys, +values)),
boost::make_zip_iterator(boost::make_tuple(keys+N, values+N)));
this will compile, but the sorted result is still wrong, because a zip_iterator only models a Readable iterator, but std::sort also needs the input to be Writable as described here, so you can't sort using zip_iterator.
A very good discussion of this problem can be found here: https://web.archive.org/web/20120422174751/http://www.stanford.edu/~dgleich/notebook/2006/03/sorting_two_arrays_simultaneou.html
Here's a possible duplicate of this question: Sorting zipped (locked) containers in C++ using boost or the STL
The approach in the link above uses std::sort, and no extra space. It doesn't employ boost::zip_iterator, just boost tuples and the boost iterator facade. Std::tuples should also work if you have an up to date compiler.
If you are happy to have one extra vector (of size_t elements), then the following approach will work in ~ o(n log n) time average case. It's fairly simple, but there will be better approaches out there if you search for them.
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
template <typename T1, typename T2>
void sortByPerm(vector<T1>& list1, vector<T2>& list2) {
const auto len = list1.size();
if (!len || len != list2.size()) throw;
// create permutation vector
vector<size_t> perms;
for (size_t i = 0; i < len; i++) perms.push_back(i);
sort(perms.begin(), perms.end(), [&](T1 a, T1 b){ return list1[a] < list1[b]; });
// order input vectors by permutation
for (size_t i = 0; i < len - 1; i++) {
swap(list1[i], list1[perms[i]]);
swap(list2[i], list2[perms[i]]);
// adjust permutation vector if required
if (i < perms[i]) {
auto d = distance(perms.begin(), find(perms.begin() + i, perms.end(), i));
swap(perms[i], perms[d]);
}
}
}
int main() {
vector<int> ints = {32, 12, 40, 8, 9, 15};
vector<double> doubles = {55.1, 33.3, 66.1, 11.1, 22.1, 44.1};
sortByPerm(ints, doubles);
copy(ints.begin(), ints.end(), ostream_iterator<int>(cout, " ")); cout << endl;
copy(doubles.begin(), doubles.end(), ostream_iterator<double>(cout, " ")); cout << endl;
}
After seeing another of your comments in another answer.
I though I would enlighten you to the std::map. This is a key value container, that preserves key order. (it is basically a binary tree, usually red black tree, but that isn't important).
size_t elements=10;
std::map<int, double> map_;
for (size_t i = 0; i < 10; ++i)
{
map_[rand()%M]=1.0*rand()/RAND_MAX;
}
//for every element in map, if you have C++11 this can be much cleaner
for (std::map<int,double>::const_iterator it=map_.begin();
it!=map_.end(); ++it)
{
std::cout << it->first << "\t" << it->second << std::endl;
}
untested, but any error should be simple syntax errors
boost::make_zip_iterator take a boost::tuple.
#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
int main(int argc, char *argv[])
{
std::vector<int> keys(10); //lets not waste time with arrays
std::vector<double> values(10);
const int M=100;
//Create the vectors.
for (size_t i = 0; i < values.size(); ++i)
{
keys[i] = rand()%M;
values[i] = 1.0*rand()/RAND_MAX;
}
//Now we use the boost zip iterator to zip the two vectors and sort them "simulatneously"
//I want to sort-by-key the keys and values arrays
std::sort ( boost::make_zip_iterator(
boost::make_tuple(keys.begin(), values.begin())),
boost::make_zip_iterator(
boost::make_tuple(keys.end(), values.end()))
);
//The values array and the corresponding keys in ascending order.
for (size_t i = 0; i < values.size(); ++i)
{
std::cout << keys[i] << "\t" << values[i] << std::endl;
}
return 0;
}