Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I need a queue that must add/remove some structs I have, such as:
struct MyObject
{
int offset;
BYTE status, data1, data2;
double beatPos;
enum Status
{
isOff = 8,
isOn = 9,
};
}
When I .Add() an element, this queue must put the element at the correct position, due to the beatPos value, which must be ordered from the lower (top of the queue, i.e. the next element I'll pop) to the upper (the last element I'll extract from it).
I see there is std::priority_queue, but I'm not sure if I can select which is the field for the ordering.
Also, once I add some structs in the list, I'd like to remove the first element that have (for example) beatPos=1,567 (which could be in the middle of the list, for example; not necessarily at the beginning).
Any clues?
What you want is a std::multiset. It takes a compare template parameter and it is defaulted to std::less for the type the container is going to store but you can specify a different comparator. To do that we can create a lambda that will compare two MyObjects and return which object should have a higher priority based on the beatPos member
auto my_compare = [](const MyObject & lhs, const MyObject & rhs)
{
return lhs.beatPos < rhs.beatPos;
}
And then we can use that like
std::multiset<MyObject, decltype(my_compare)> data(my_compare);
This will give you an ordered container that can store multiple objects with the same beatPos and allow you access into the middle of the container.
You can use std::multiset with a user-defined comparator. For example:
bool MyObjectComp(const MyObject& lhs, const MyObject& rhs) {
return lhs.beatPos < rhs.beatPos;
}
typedef std::set<MyObject, MyObjectComp> MyObjectSet;
Now the ordering within MyObjectSet is always from lowest to highest beatPos. You can search using lower_bound() and upper_bound(), and you can get the smallest value using begin().
Note that due to the nature of double values (IEEE floating point), exact comparison may not work, so you can't necessarily say mySet.find(0.5) but you can say mySet.upper_bound(0.49999).
The same user-defined comparator can be used for priority_queue as well, but that container does not support searching for an element by value, which is one of your requirements.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 months ago.
Improve this question
Good evening!
I have a task: implement any function to sort array and then check if two arrays(the input and the output) are the same(meaning that the values are the same). Values in array are random, so there my be something like [5,2,5,5,6,-1,3,0,84305]
I was thinking about checking if elements are in both arrays, then if yes - assign them to some rubbish value(I was hoping to go for NULL, but apparently it works only in Python), and then if any array has something that is not our rubbish value return false, but I am not sure about this variant, maybe someone has better ideas? That would be very helpful
If the values are unique, insert all values from the first array in an std::unordered_set and remove all values from the second array from it. If your set is empty at the end, or if any removal fails, then the sets aren't "equal" as per your definition.
If the values aren't unique, you'll need to use an std::unordered_map with the value the count of times that particular value was seen. When inserting, you increment the value (or set to 1 if it's the first time you've seen it). When removing, you decrement it. The sets aren't "equal" if you can't find an entry to do the removal step, or if there's any value in the map that's not 0.
So for your sort function, it would be something simple like this
template<typename T, int size>
auto sort_v(T (&arr) [size])
{
std::sort(std::begin(arr), std::end(arr));
return v;
}
and then to compare them you could do something like:
template<typename T, int size>
auto compare(T* arr, T* arr2) -> bool
{
for(int i = 0; i < size; i++)
{
if(arr[i] != arr2[i])
{
return false;
}
}
return true;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am creating function, which takes a vector of operators( different matrices). Operators can be provided in different ordering ( from the smallest to biggest or other way around).
I need to create for loop based on ordering
for(auto tr = operators.begin(); tr != operators.end() ; ++tr )
or
for(auto tr = operators.end(); tr != operators.begin() ; --tr )
content inside of loop stays same
is there any way how to do this automatically? maybe based on some help input parameter?
You can support this by having your function consume a pair of iterators (a "range") instead of a complete matrix or vector. For example:
template <typename Iterator>
void print(Iterator begin, Iterator end) {
for(auto tr = begin; tr != end; ++tr)
; // ...
}
This way, you can pass any sort of range in: forward, reverse, or others. This is how much of the STL is designed.
If you use a std::vector for example, you'd invoke the above like so:
std::vector<int> vec;
print(vec.begin(), vec.end()); // forward
print(vec.rbegin(), vec.rend()); // reverse
Although, technically, an end() iterator can often be decremented and dereferenced safely, you are relying on specific properties that not all iterators are guaranteed to have.
A number of standard containers [some introduced in C++11 do not] have both forward iterators (which iterate through elements in order) and reverse iterators (which iterate over elements in the opposite order). The counterparts of begin() and end() are rbegin() and rend() respectively.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I've been searching lots of sites and browsed few books about this but failed to come across to find good sources about implementation of how to dynamically (within execution of the program) compare different datatypes in a class with less- < or , bigger than > operators.
Let's say we've the following snippet code:
#include <iostream>
using namespace std;
class OP
{
private:
string alias;
float locatorX;
int coordinate;
public:
bool operator<(const OP& rhs)
{
return (this->locatorX < rhs.locatorX);
//Here! How do I do to make the compiler understand that
//I compare i.e alias or coordinate whenever I need?
//I tried with:
return (this->coordinate < rhs.coordinate, this->alias < rhs.alias);
//But it didn't really do the trick when implemented
//a sort algorithm inside main as it failed to sort a string array.
}
};
EDIT:
Since most of the kind people here did not understand the question, here is a scenario which you hopefully get.
Let us say we want to create a map that accepts a string, int and float types. We create a function inside of the class OP that accepts all given datatypes and saves them in the created class array. And so we have i.e 15 records in our class array.
How do I do so that I can dynamically bubble sort (with help of < operator), alias (string) locatorX(float) and coordinate(int) (whichever I choose) in ascending order with less than operator?
For example I somewhat need to sort coordinates or alias (if needed) at run time. How do I do this?
Example output:
(First position in array):
"Albert street 5th"
Coordinate: 1691
locatorX: 19.52165
(Second position in array):
"Main street 7th alley"
Coordinate: 59
locatorX: 8175. 12
(Third position in array):
"Elm/Kentucky"
Coordinate: 9517
locatorX: 271.41
Typically you'd create a separate comparator for each comparison you wish to implement. You can't munge them into a single operator< and, although you could technically produce a different function that performed a different comparison depending on the value of some new, third argument, it would be incompatible with almost everything currently existing that knows how to work with comparators.
This is one of the scenarios in which operator overloading specifically is the wrong tool for the job.
There seems to be several ways to do so:
Switch between comparison functions at the call site
You have to define separate compare functions for different fields.
std::vector<Object> v;
enum class OrderBy
{
alias,
coordinate
}
OrderBy order_by = get_orderBy_from_user();
switch (order_by)
{
case OrderBy::alias:
std::sort(v.begin(), v.end(), compare_by_alias());
break;
case OrderBy::coordinate:
std::sort(v.begin(), v.end(), compare_by_coordinate());
break;
}
Make a choice inside a comparison function.
You must communicate the choice of ordering field somehow into the function.
The options are: global or singleton "configuration" object, member variable in the comparison class. I would avoid any globals, thus the second option:
struct compare_by_field
{
OrderBy order_by_;
compare_by_field(OrderBy order_by) : order_by_(order_by)
{}
bool operator()(const Object & lhs, const Object & rhs) const
{
switch (order_by_)
{
case OrderBy::alias:
return lhs.alias < rhs.alias;
case OrderBy::coordinate:
return lhs.coordinate < rhs.coordinate;
}
}
}
std::sort(v.begin(), v.end(), compare_by_field(get_order_by_from_user()));
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Is it any nice way to call STL algorithms on an integer range?
For example I have a collection "col" with access to it's elements only via GetElement(int) method. Is it possible to use find_if function to find something in that collection?
I would like to call something like that:
auto element =
find_if(0, col.Size(), [&col] (int i) {
return predicate(col.GetElement(i));
});
I'm looking for an STL or any other library solution.
With standard C++? Yes, if you write a custom element iterator. Then, your code is easily simplified to:
auto element = find_if(col.begin(), col.end(), predicate);
It's not possible to do something closer to what you had in mind with the standard library, but it is with Boost, which is an incredible C++ library that you really ought to have. Boost has a counting iterator: http://www.boost.org/doc/libs/1_55_0/libs/iterator/doc/counting_iterator.html
How would you fill up a vector with the numbers zero through one hundred using std::copy()? The only iterator operation missing from builtin integer types is an operator*() that returns the current value of the integer. The counting iterator adaptor adds this crucial piece of functionality to whatever type it wraps. One can use the counting iterator adaptor not only with integer types, but with any incrementable type.
#include <boost\counting_iterator.hpp> //or something, not sure of exact header
int main() {
boost::counting_iterator<int> first(0);
boost::counting_iterator<int> last(col.Size());
auto element = find_if(first, last, [&col](int i) {return predicate(col.GetElement(i);});
}
Additionally, boost also has ranges. They don't really help you much in this exact situation, but it's related, so I'll mention it:
#include <boost\range\irange.hpp>
int main() {
for (int index: boost::range::irange<int>(0, col.Size()) )
{
std::cout << element; //counts from 0 to col.Size()
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Is it possible to use the tools only needing Iterators and a function-pointer from the module <algorithm> on PyObjects ?
The concrete problem I want to solve (it is constructed to learn from it):
I have a huge list of IDs stored in a python-list
Now I want to perform a std::binary_search on this list, using a module written in C++
One way could be to access the python-list as c-array, constructing a vector from it (which uses the pointers/ does not copy), doing the binary_search and export the array as PyObject.
Would that be possible?
Well, a binary search isn't that complicated, so why don't you simply code one based on a range of indices instead of iterators? I believe that a list conforms to the sequence protocol of Python, so that should be pretty easy.
If you really want to use the binary_search() algorithm for a learning experience, there is also the possibility to create STL-style iterators on top of the Python sequence. All you need is a pointer to the sequence and an index to create a random-access iterator. If you want to, you can also transparently convert the Python objects in the list into an according ID type (some integer type, I guess).
struct iterator
{
// typedefs required for fully compliant STL-style iterators
typedef PyObject* value_type;
iterator(PyObject* seqeunce, Py_ssize_t position):
m_sequence(sequence), m_position(position)
{
assert(PySequence_Check(m_sequence));
assert(m_position >= 0);
assert(m_position <= PySequence_GetSize(m_sequence));
}
value_type operator*() const
{
assert(m_position < PySequence_GetSize(m_sequence));
return PySequence_GetItem(m_sequence, m_position);
}
iterator& operator++()
{
assert(m_position <= PySequence_GetSize(m_sequence));
++m_position;
return *this;
}
iterator& operator+=(size_t l)
{
m_position += l;
return *this;
}
};
I haven't compiled this and probably forgot a few parts, but I guess you get the idea. Just init two iterators, one with an offset of zero and one with an offset of the size of the container and give those to binary_search().