Specifying iterator value in stable_sort function - c++11

I am using the below code to sort rectangles.
In the stable_sort function, how can I specify the iterator values other than boundRect.begin and boundRect.end. I want to sort the elements between index 5 to 10. How can I specify these in the stable_sort function? Please guide me.
stable_sort( boundRect.begin(), boundRect.end(), compareX_rect );
bool compareX_rect(const Rect & a, const Rect &b) {
return a.x <= b.x;
}

Since stable_sort requires random access iterators, you can do simple addition on the iterators:
stable_sort(boundRect.begin()+5, boundRect.begin()+10, /* ... */
Unless you're dealing with an ancient (pre-C++11) compiler, you can use a lambda expression for the comparison as well:
stable_sort(boundRect.begin()+5, boundRect.begin()+10,
[](const Rect & a, const Rect &b) { return a.x < b.x; });
This not only shorter and easier to read, but will often be faster as well (not that it's likely to matter when you're only sorting 5 elements).

Related

STL algorithm for splitting a vector into multiple smaller ones based on lambda

Let's say I have a vector containing a struct with a member describing its target vector.
struct Foo
{
int target;
static const int A = 0;
static const int B = 1;
static const int C = 2;
};
std::vector<Foo> elements;
std::vector<Foo> As;
std::vector<Foo> Bs;
std::vector<Foo> Cs;
std::vector<Foo> others;
Now I want to move each Foo in one of the four other vectors based on the value of Target.
For example
auto elements = std::vector<Foo>{ {Foo::A}, {Foo::A}, {Foo::B} };
Should result in two elements in As, one in Bs and none in Cs or others. Elements should be empty afterwards.
I could as well do it myself, but I wonder if there is an STL algorithm I could use to do its job.
Standard algorithms usually don't operate on multiple output destinations, so it's hard to come up with a suitable solution here when you want to abstract away the destination containers through output iterators. What might come closest is std::copy_if. This could look like
// Help predicate creation:
auto pred = [](int target){ return [target](const Foo& f){ return f.target == target; }; };
std::copy_if(elements.begin(), elements.end(), std::back_inserter(As), pred(Foo::A));
std::copy_if(elements.begin(), elements.end(), std::back_inserter(Bs), pred(Foo::B));
std::copy_if(elements.begin(), elements.end(), std::back_inserter(Cs), pred(Foo::C));
std::copy_if(elements.begin(), elements.end(), std::back_inserter(others),
[](const Foo& f){ return false; /* TODO */ });
elements.clear();
If copying is more expensive than move-construction, you should pass std::make_move_iterator(elements.begin()) and the same for elements.end() to the algorithm. The issue here is that this doesn't scale. std::copy_if linearly traverses the input range, and the above has to do this four times. One traversal can be obtained e.g. like the following.
auto doTheWork = [&As, &Bs, &Cs, &others](const Foo& foo) {
if (foo.target == Foo::A)
As.push_back(foo);
else if (foo.target == Foo::B)
Bs.push_back(foo);
else if (foo.target == Foo::C)
Cs.push_back(foo);
else
others.push_back(foo);
};
std::for_each(elements.begin(), elements.end(), doTheWork);
In this scenario, we have at least employed a standard algorithm, but shifted the logic into a rather ugly lambda. Note that the above lambda will always copy its arguments, it needs some adjustments to properly work with std::move_iterators.
Sometimes, a good old range based for loop is the most readable solution.

Can anybody please describe this portion of code of the Dijkstra algorithm

I can't understand this given portion of the Dijkstra algorithm. I want to understand this portion of code line by line.
The code:
bool operator < (const DATA &p) const { return p.dist > dist; }
I have the basic knowledge of c/c++ code.
bool operator < (const DATA &p) const {
return p.dist > dist;
}
This is less than < operator overloading.
You are passing DATA &p prefixed by const which means p is passed by reference and it can't be modified or altered inside the function.
The function started with const { means there will be no write/modify operation inside the method.
p.dist > dist means after pushing into priority_queue, comparing between two Data will follow this criteria - when Data having smaller dist will be appeared first in the priority queue than Data with longer dist. This sounds contradictory but this is true because priority_queue is by-default a max heap.

storing map<string, struct> into vector to sort

I have the following code that I am trying. I am trying to sort it by ascending or descending size, and from z-a (three different sorts). I can't figure out how to even store it in the vector let alone sort it. Thanks for the help!
struct countSize {
int count;
uintmax_t size;
void sortMap(map<string, countSize> &extCount)
{
// Copy
vector<string, countSize> v(extCount.begin(), extCount.end());
// Sort the vector according to either file size or desc alphabetically
//print
}
int main()
{
map<string, countSize> mp;
mp["hello"] = { 1, 200 };
mp["Ace"] = { 5, 600 };
mp["hi"] = { 3, 300 };
mp["br"] = { 2, 100 };
sortMap(mp);
}
If you iterate over a map, you get a stream of std::pair<const X, Y>. That's a bit awkward for storing in a vector, because of the const. One solution is to just drop the const:
using my_map = std::map<std::string, countSize>;
// Mutable element type.
using my_map_element = std::pair<typename my_map::key_type,
typename my_map::mapped_type>;
using my_element_list = std::vector<my_map_element>;
Then it's very straight-forward to build a vector and sort it. Here, we use a template for the comparison function which makes it a lot easier to use a lambda for the comparator:
template<typename Functor>
my_element_list sortMap(const my_map& the_map, Functor compare) {
my_element_list v(the_map.begin(), the_map.end());
std::sort(v.begin(), v.end(), compare);
return v;
}
Unlike your code, this returns the sorted list. The caller can print the list if desired. See, for example, the example live on Coliru.
That's not really ideal, though. If the individual elements of the map are at all complicated, it may well be more efficient to make a vector of pointers to the elements, rather than copies of the elements. Amongst other things, this does not require readjusting the element type, and that makes it possible to be agnostic about the base container type as well. However, you need to remember that the comparison functor will now receive pointers to the elements to be compared. See the modified example.

Foreach loops over Eigen matrices?

Is it possible to use the foreach syntax of C++11 with Eigen matrices? For instance, if I wanted to compute the sum of a matrix (I know there's a builtin function for this, I just wanted a simple example) I'd like to do something like
Matrix2d a;
a << 1, 2,
3, 4;
double sum = 0.0;
for(double d : a) {
sum += d;
}
However Eigen doesn't seem to allow it. Is there a more natural way to do a foreach loop over elements of an Eigen matrix?
Range-based for loops need the methods .begin() and .end() to be implemented on that type, which they are not for Eigen matrices. However, as a pointer is also a valid random access iterator in C++, the methods .data() and .data() + .size() can be used for the begin and end functions for any of the STL algorithms.
For your particular case, it's more useful to obtain start and end iterators yourself, and pass both iterators to a standard algorithm:
auto const sum = std::accumulate(a.data(), a.data()+a.size(), 0.0);
If you have another function that really needs range-based for, you need to provide implementations of begin() and end() in the same namespace as the type (for argument-dependent lookup). I'll use C++14 here, to save typing:
namespace Eigen
{
auto begin(Matrix2d& m) { return m.data(); }
auto end(Matrix2d& m) { return m.data()+m.size(); }
auto begin(Matrix2d const& m) { return m.data(); }
auto end(Matrix2d const& m) { return m.data()+m.size(); }
}
STL style iterator support has been added to Eigen in version 3.4.
See https://eigen.tuxfamily.org/dox-devel/group__TutorialSTL.html
For OP's question, you can do the following:
Matrix2d A;
A << 1, 2,
3, 4;
double sum = 0.0;
for(auto x : A.reshaped())
sum += x;
A pointer to the data array of the matrix can be obtained using the member function .data().
The size of the data array can also be obtained using the member function .size().
Using these two, we now have the pointers to the first element and end of the array as a.data() and a.data()+a.size().
Also, we know that an std::vector can be initialized using iterators (or array pointers in our case).
Thus, we can obtain a vector of doubles that wraps the matrix elements with std::vector<double>(a.data(), a.data()+a.size()).
This vector can be used with the range-based for loop syntax that is included in your code snippet as:
Matrix2d a;
a << 1, 2,
3, 4;
double sum = 0.0;
for(double d : std::vector<double>(a.data(), a.data()+a.size())) {
sum += d;
}

glib: sort by multiple attributes

I am using glib to sort:
gint cmp_values_by_attr1(gpointer a, gpointer b) {
my_strcut *seq_a = *((my_strcut**) a);
my_strcut *seq_b = *((my_strcut**) b);
return (seq_a->attr1 - seq_b->attr1);
}
values = g_ptr_array_sized_new(4);
v = new_struct();
g_ptr_array_add(values, v);
...
g_ptr_array_sort(values, (GCompFunction) cmp_values_by_attr1);
Now inside my array, I would like to sort first by attr1 and then by attr2. How to implement?
It's quite simple—the comparison function returns less than, equal to, or greater than zero depending on whether the first value is less than, equal to, or greater than the second value. All you need to do is compare the first attributes and if the return value is not equal to zero return the result, otherwise compare the second attributes and return the result:
gint comp_values (gpointer a, gpointer b) {
gint res;
my_strcut *seq_a = *((my_strcut**) a);
my_strcut *seq_b = *((my_strcut**) b);
res = seq_a->attr1 - seq_b->attr1;
if (res == 0) {
res = (seq_a->attr2 - seq_b->attr2);
}
return res;
}
I have used some 'hack' to implement this sorting.
Make the two attributes to sort to be uint32_t types.
Add another attribute uint64_t for_sort to my struct
Shift the upper 32 bits of for_sort to be attr1
The lower 32 bits of for_sort to be attr2
Sort the array by for_sort, then the items are first sorted by attr1, then by attr2.
I have implemented and verified that it is working.
Disadvantages:
Extra memory to add for_sort
Extra processing
If the sorting attributes are in other types, need to change accordingly.

Resources