Correct way to write only the first element of a c++ stl vector - c++

I have a c++ code that at one part it stored some values of a measurement in a vector and this vector is a part of set of data schema which is serialized and then sent to a streamer.
There is new requirement that for a specific case I need just one value of the measurement which is always rewritten with the latest one, but I don't want to change the vector variable in order to keep the same schema. So I thought that for that case to rewrite each time the first element of the vector, something like this
vector<int> store_measurements;
int measurement = 10;
if (condition == "several_values")
{
store_measurements.pushback(measurement);
}
else
{
store_measurements.at(0) = measurement ;
}
It seems to work fine when the vector is not cleared, but I'd like to ask if this is the correct way to do that or there is a more preferable way to do it?

You can use the front() function.
vector<int> store_measurements;
int measurement = 10;
if (condition == "several_values")
{
store_measurements.push_back(measurement);
}
else
{
store_measurements.resize(1);
store_measurements.front() = measurement ;
}
Edit:
Based on the comments I added store_measurements.resize(1); before the assignment

I would probably use assign() which replaces all the values in the vector like this:
if (condition == "several_values")
{
store_measurements.push_back(measurement);
}
else
{
store_measurements.assign(1, measurement);
}

Related

RemoveAt from StructArray Ue4

I struggle a bit with deleting struct from my TArray of structs.My struct contains AudioComponent and float.I was using Array.RemoveAt(index), but what i got from this was only removing half of my struct, which is AudioComponent.
Why is that? My function Removing elements looks like this:
void RemoveArrayElement( UAudioComponent AudioComponent )
{
for( int i=0; i<Array.Num(); i++ )
{
if( AudioComponent == Array[i].AudioComponent )
{
Array.RemoveAt( i );
}
}
}
What i want to achieve is completely deleting index, AudioComponent with it's float.
There are few issues with your code. As others mentioned in comments, you should use pointers. And if I'm not mistaken, you aren't allowed to use construction like this:
UPROPERTY()
TArray<UAudioComponent> invalidArray;
You should use UPROPERTY macro, otherwise your properties could and probably will be garbage collected. UPROPERTY wiki.
Next thing is that you are changing array over which you are iterating. I wrote few approaches, let's look at them:
void RemoveArrayElement(UAudioComponent* AudioComponent)
{
TArray<UAudioComponent*> audioArray; // array will be initialized somewhere else, this is for demo purpose.
// you always should check your pointers for validity
if (!AudioComponent || !AudioComponent->IsValidLowLevel() || AudioComponent->IsPendingKill())
return;
// Correct approach 1 (multiple):
TQueue<UAudioComponent*> toDelete;
for (int i = 0; i < audioArray.Num(); i++)
{
auto item = audioArray[i];
if (AudioComponent == item || true) // we simulate another condition for multiselect
{
toDelete.Enqueue(item);
}
}
// better approach for iteration:
for (auto item : audioArray)
if (item == AudioComponent || true) // we simulate another condition for multiselect
toDelete.Enqueue(item);
// finalize deletion in approach 1
UAudioComponent* deleteItem;
while (toDelete.Dequeue(deleteItem))
audioArray.Remove(deleteItem);
// almost correct approach 2 (single) :
UAudioComponent* foundItem;
for (auto item : audioArray)
if (item == AudioComponent)
{
foundItem = item;
break; // we can skip rest - but we must be sure, that items were added to collection using AddUnique(...)
}
if (foundItem)
audioArray.Remove(foundItem);
// correct and the best - approach 3 (single)
audioArray.Remove(AudioComponent);
}
First keep in mind that comparing two objects does not necessarily lead to the expected result of equality. Using the == operator means executing a function (bool operator==(L, R);) that specifies what should happen. So if you did not overload the == operator then you don't know what using it would result to unless you look at the source code where it's defined. Since you want to remove the exact audio component and not an instance of it that looks the same, you want to use pointers in your array. That also helps performance since your are not copying the whole component when calling RemoveArrayElement(...); but a single pointer. Also when there are two identical audio components stored in the array and they are at index a and a+1, then removing the audio component at index a the next iteration would skip your second audio component since all upper indexes are decremented by one.

vector size remaining static after pushback() calls for powerset function

I wrote the following function, as an implementation of this algorithm/approach, to generate the power-set (set of all subsets) of a given string:
vector<string> getAllSubsets(string a, vector<string> allSubsets)
{
if(a.length() == 1)
{
// Base case,
allSubsets.push_back("");
allSubsets.push_back(a);
}
else {
vector<string> temp = getAllSubsets(a.substr(0,a.length()-1),allSubsets);
vector<string> with_n = temp;
vector<string> without_n = temp;
for(int i = 0;i < temp.size()-1;i++)
{
allSubsets.push_back(with_n[i] + a[a.length()-1]);
allSubsets.push_back(without_n[i]);
}
}
return allSubsets;
}
however, someone appears to be going wrong: the size of temp and allSubsets remains static from recursive call to recursive call, when they should be increasing due to the push_back() calls. is there any reason why this would take place?
It's because you have an off-by-one error. Because this occurs in your next-to-base case, you are never inserting any entries.
Since the first invalid index is temp.size(), i < temp.size() means that you will always have a valid index. Subtracting 1 means that you are missing the last element of the vector.
It's worth noting that passing allSubsets in as a parameter is kinda silly because it's always empty. This kind of algorithm simply doesn't require a second parameter. And secondly, you could be more efficient using hash sets that can perform deduplication for you simply and quickly.

A single iterator of vectorS

Is there an efficient way to have a single iterator iterate on the concatenation of 2 objects vector, as if they were one?
The two vectors contain the same data type of course.
UPDATE:
I think I should have put more details about my question and my context. This may answer some of the questions:
In fact I am having one attribute that store the last position of that iterator and inside one method I start to iterate from the last position where I stopped in the previous call, which might be in the first vector or in the second one.
What about this solution? It may be not elegant, but I guess it respects the standard. right?
vector<Whatever>::iterator it = vectorA.begin();
bool loopOnVectorA = true;
while(true) {
// My stuff here
if (loopOnVectorA && it == vectorA.end())
{
it = vectorB.begin();
loopOnVectorA = false;
}
else if (it == vectorB.end())
{
break;
}
else
{
varPtrIt++;
}
}

c++ - Tricky Method - need solution

The array of objects tArray contains buyer names and the numshares of there purchases, each buyer can be in the array of objects more than once. I have to return in an array the names of the five largest buyers.
I attempted to run two arrays in parallel with the buyer name and there total volume in another array.
my method in general flawed as i am getting wrong results, how can I solve this problem.
Thanks
ntransactions = the number of transactions in the array
string* Analyser::topFiveBuyers()
{
//set size and add buyer names for comparison.
const int sSize = 5;
string *calcString = new string[sSize];
calcString[0] = tArray[0].buyerName;
calcString[1] = tArray[1].buyerName;
calcString[2] = tArray[2].buyerName;
calcString[3] = tArray[3].buyerName;
calcString[4] = tArray[4].buyerName;
int calcTotal[sSize] = {INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN};
//checks transactions
for (int i = 0; i<nTransactions; i++)
{
//compares with arrays
for(int j =0; j<sSize; j++)
{
//checks if the same buyer and then increase his total
if(tArray[i].buyerName == calcString[j])
{
calcTotal[j] += tArray[i].numShares;
break;
}
//checks if shares is great then current total then replaces
if(tArray[i].numShares > calcTotal[j])
{
calcTotal[j] = tArray[i].numShares;
calcString[j] = tArray[i].buyerName;
break;
}
}
}
return calcString;
}
Assuming you're allowed to, I'd start by accumulating the values into an std::map:
std::map<std::string, int> totals;
for (int i=0; i<ntransactions; i++)
totals[tarray[i].buyername] += tarray[i].numshares;
This will add up the total number of shares for each buyer. Then you want to copy that data to an std::vector, and get the top 5 by number of shares. For the moment, I'm going to assume your struct (with buyername and numshares as members) is named transaction.
std::vector<transaction> top5;
std::copy(totals.begin(), totals.end(), std::back_inserter(top5));
std::nth_element(top5.begin(), top5.begin()+5, top5.end(), by_shares());
For this to work, you'll need a comparison functor named by_shares that looks something like:
struct by_shares {
bool operator()(transaction const &a, transaction const &b) {
return b.numshares < a.numshares;
}
};
Or, if you're using a compiler new enough to support it, you could use a lambda instead of an explicit functor for the comparison:
std::nth_element(totals.begin(), totals.end()-5, totals.end(),
[](transaction const &a, transaction const &b) {
return b.numshares < a.numshares;
});
Either way, after nth_element completes, your top 5 will be in the first 5 elements of the vector. I've reversed the normal comparison to do this, so it's basically working in descending order. Alternatively, you could use ascending order, but specify the spot 5 from the end of the collection instead of 5 from the beginning.
I should add that there are other ways to do this -- for example, a Boost bimap would do the job pretty nicely as well. Given that this sounds like homework, my guess is that a pre-packaged solution like bimap that handles virtually the entire job for you probably would't/won't be allowed (and even std::map may be prohibited for pretty much the same reason).
As you can have several times the same buyer, you must store a counter for all buyers, not only for 5 of them as there is no way to know that a buyer you remove from the top 5 should not be part of this top 5 (as more items could be linked to this buyer later in tArray).
I would suggest to use a stl map with key being buyer name and value the number of items. You fill it by iterating on tArray and sum all items bought by the same buyer.
Then you can iterate on the map and retrieve the 5 top buyers easily as you have only one entry per buyer.
When the outer loop start, the index i is zero, and the same for the inner loop. This means that the first condition checks tArray[0].buyerName == calcString[0] which is equal as you set it that way before the loops. This leads to calcTotal[0] is increased from -2147483648 and leaving the inner loop.
I'm not certain, but this doesn't seem like something one would want.

Fastest container or algorithm for unique reusable ids in C++

I have a need for unique reusable ids. The user can choose his own ids or he can ask for a free one. The API is basically
class IdManager {
public:
int AllocateId(); // Allocates an id
void FreeId(int id); // Frees an id so it can be used again
bool MarkAsUsed(int id); // Let's the user register an id.
// returns false if the id was already used.
bool IsUsed(int id); // Returns true if id is used.
};
Assume ids happen to start at 1 and progress, 2, 3, etc. This is not a requirement, just to help illustrate.
IdManager mgr;
mgr.MarkAsUsed(3);
printf ("%d\n", mgr.AllocateId());
printf ("%d\n", mgr.AllocateId());
printf ("%d\n", mgr.AllocateId());
Would print
1
2
4
Because id 3 has already been declared used.
What's the best container / algorithm to both remember which ids are used AND find a free id?
If you want to know the a specific use case, OpenGL's glGenTextures, glBindTexture and glDeleteTextures are equivalent to AllocateId, MarkAsUsed and FreeId
My idea is to use std::set and Boost.interval so IdManager will hold a set of non-overlapping intervals of free IDs.
AllocateId() is very simple and very quick and just returns the left boundary of the first free interval. Other two methods are slightly more difficult because it might be necessary to split an existing interval or to merge two adjacent intervals. However they are also quite fast.
So this is an illustration of the idea of using intervals:
IdManager mgr; // Now there is one interval of free IDs: [1..MAX_INT]
mgr.MarkAsUsed(3);// Now there are two interval of free IDs: [1..2], [4..MAX_INT]
mgr.AllocateId(); // two intervals: [2..2], [4..MAX_INT]
mgr.AllocateId(); // Now there is one interval: [4..MAX_INT]
mgr.AllocateId(); // Now there is one interval: [5..MAX_INT]
This is code itself:
#include <boost/numeric/interval.hpp>
#include <limits>
#include <set>
#include <iostream>
class id_interval
{
public:
id_interval(int ll, int uu) : value_(ll,uu) {}
bool operator < (const id_interval& ) const;
int left() const { return value_.lower(); }
int right() const { return value_.upper(); }
private:
boost::numeric::interval<int> value_;
};
class IdManager {
public:
IdManager();
int AllocateId(); // Allocates an id
void FreeId(int id); // Frees an id so it can be used again
bool MarkAsUsed(int id); // Let's the user register an id.
private:
typedef std::set<id_interval> id_intervals_t;
id_intervals_t free_;
};
IdManager::IdManager()
{
free_.insert(id_interval(1, std::numeric_limits<int>::max()));
}
int IdManager::AllocateId()
{
id_interval first = *(free_.begin());
int free_id = first.left();
free_.erase(free_.begin());
if (first.left() + 1 <= first.right()) {
free_.insert(id_interval(first.left() + 1 , first.right()));
}
return free_id;
}
bool IdManager::MarkAsUsed(int id)
{
id_intervals_t::iterator it = free_.find(id_interval(id,id));
if (it == free_.end()) {
return false;
} else {
id_interval free_interval = *(it);
free_.erase (it);
if (free_interval.left() < id) {
free_.insert(id_interval(free_interval.left(), id-1));
}
if (id +1 <= free_interval.right() ) {
free_.insert(id_interval(id+1, free_interval.right()));
}
return true;
}
}
void IdManager::FreeId(int id)
{
id_intervals_t::iterator it = free_.find(id_interval(id,id));
if (it != free_.end() && it->left() <= id && it->right() > id) {
return ;
}
it = free_.upper_bound(id_interval(id,id));
if (it == free_.end()) {
return ;
} else {
id_interval free_interval = *(it);
if (id + 1 != free_interval.left()) {
free_.insert(id_interval(id, id));
} else {
if (it != free_.begin()) {
id_intervals_t::iterator it_2 = it;
--it_2;
if (it_2->right() + 1 == id ) {
id_interval free_interval_2 = *(it_2);
free_.erase(it);
free_.erase(it_2);
free_.insert(
id_interval(free_interval_2.left(),
free_interval.right()));
} else {
free_.erase(it);
free_.insert(id_interval(id, free_interval.right()));
}
} else {
free_.erase(it);
free_.insert(id_interval(id, free_interval.right()));
}
}
}
}
bool id_interval::operator < (const id_interval& s) const
{
return
(value_.lower() < s.value_.lower()) &&
(value_.upper() < s.value_.lower());
}
int main()
{
IdManager mgr;
mgr.MarkAsUsed(3);
printf ("%d\n", mgr.AllocateId());
printf ("%d\n", mgr.AllocateId());
printf ("%d\n", mgr.AllocateId());
return 0;
}
It would be good to know how many ids you're supposed to keep track of. If there's only a hundred or so, a simple set would do, with linear traversal to get a new id. If it's more like a few thousands, then of course the linear traversal will become a performance killer, especially considering the cache unfriendliness of the set.
Personally, I would go for the following:
set, which helps keeping track of the ids easily O(log N)
proposing the new id as the current maximum + 1... O(1)
If you don't allocate (in the lifetime of the application) more than max<int>() ids, it should be fine, otherwise... use a larger type (make it unsigned, use a long or long long) that's the easiest to begin with.
And if it does not suffice, leave me a comment and I'll edit and search for more complicated solutions. But the more complicated the book-keeping, the longer it'll take to execute in practice and the higher the chances of making a mistake.
But I don't think you have to guarantee the id must starts from 1. You can just make sure the available id must be larger than all allocated ids.
Like if the 3 is registered first, then the next available id can just be 4. I don't think it is necessary to use 1.
I'm assuming that you want to be able to use all available values for the Id type and that you want to reuse freed Ids? I'm also assuming that you'll lock the collection if you're using it from more than one thread...
I'd create a class with a set to store the allocated ids, a list to store the free ids and a max allocated value to prevent me having to preload the free id list with every available id.
So you start off with an empty set of allocated ids and empty list of free ids and the max allocated as 0. You allocate, take the head of the free list if there is one, else take max, check it's not in your set of allocated ids as it might be if someone reserved it, if it is, increment max and try again, if not add it to the set and return it.
When you free an id you simply check it's in your set and if so push it on your free list.
To reserve an id you simply check the set and if not present add it.
This recycles ids quickly, which may or may not be good for you, that is, allocate(), free(), allocate() will give you the same id back if no other threads are accessing the collection.
Compressed vector. But I don't think any container would make noticeable difference.
Normally, i'd say stick to an simple implementation until you have an idea of which methods are used most. Premature tuning might prove wrong. Use the simple implementation, and log its use, then you can optimize from the functions that are used the most. No use in optimizing for quick removal or quick allocation if you only need a couple of hundred ids and a simple vector would be enough.
Similar to skwllsp, I'd keep track of the ranges that have not been allocated, but my methods are slightly different. The base container would be a map, with the key being the upper bound of the range and the value being the lower bound.
IdManager::IdManager()
{
m_map.insert(std::make_pair(std::numeric_limits<int>::max(), 1);
}
int IdManager::AllocateId()
{
assert(!m_map.empty());
MyMap::iterator p = m_map.begin();
int id = p->second;
++p->second;
if (p->second > p->first)
m_map.erase(p);
return id;
}
void IdManager::FreeId(int id)
{
// I'll fill this in later
}
bool IdManager::MarkAsUsed(int id)
{
MyMap::iterator p = m_map.lower_bound(id);
// return false if the ID is already allocated
if (p == m_map.end() || id < p->second || id > p->first)))
return false;
// first thunderstorm of the season, I'll leave this for now before the power glitches
}
bool IdManager::IsUsed(int id)
{
MyMap::iterator p = m_map.lower_bound(id);
return (p != m_map.end() && id >= p->second && id <= p->first);
}
So a friend pointed out that in this case a hash might be better. Most OpenGL programs don't use more than a few thousand ids so a hash with say 4096 slots is almost guaranteed to have only 1 or 2 entries per slot. There is some degenerate case where lots of ids might go in 1 slot but that's seriously unlikely. Using a hash would make AllocateID much slower but a set could be used for that. Allocating being slower is less important than InUse being fast for my use case.