Reputation: 1455
I have an array that looks like this (the real one is much longer, with around 150 elements):
static const MyConfig m_Original[] =
{
{0x01, 0x04, 0},
{0x02, 0x0A, 0},
{0x03, 0x54, 0},
{0x01, 0x05, 0},
{0xA1, 0xE5, 0},
{0xA2, 0x6B, 0},
{0xA3, 0x2B, 0},
{0xA1, 0xE3, 0},
};
In certain cases I would like to use almost the same array, but with a couple changes.
So I did a "patch" array:
static const MyConfig m_Patch[] =
{
{0x01, 0x0F, 0},
{0x02, 0x0F, 0},
{0xA1, 0xFF, 0},
};
Note that the it is the only second value of each element (the value
) the one that changes.
So, I would like to replace those 3 (maybe more in real life) values from the original array. And! as you see, some value are repeated, all repetitions should be replaced.
The two immediate solutions are:
Just create a new array with the needed values (but then I'm allocating a big array that I will never use.
Write a for
loop comparing each element of each array and replacing if exists, which doesn't seem elegant (maybe I'm wrong (?))
The question: is there an optimal way of achieving this?
So at the end I would like m_Original
to look like:
{0x01, 0x0F, 0}, => Replaced
{0x02, 0x0F, 0}, => Replaced
{0x03, 0x54, 0},
{0x01, 0x0F, 0}, => Replaced
{0xA1, 0xFF, 0}, => Replaced
{0xA2, 0x6B, 0},
{0xA3, 0x2B, 0},
{0xA1, 0xFF, 0}, => Replaced
FYI:
typedef struct
{
uint16_t Addr;
uint16_t Value;
uint32_t time;
} MyConfig ;
EDIT: m_Original
should not be sorted, its order is important
Upvotes: 0
Views: 851
Reputation: 2225
Is there a reason you do not want to use a std::map or std::vector? However this is a possible solution with vector. It can be modified to use std::array if you like:
#include <vector>
#include <cstdint>
namespace { // Prefer anonymous namespaces before static
struct MyConfig // Use c++ syntax
{
uint16_t Addr;
uint16_t Value;
uint32_t time;
};
const std::vector<MyConfig> m_Original =
{
{0x01, 0x04, 0},
{0x02, 0x0A, 0},
{0x03, 0x54, 0},
{0x01, 0x05, 0},
{0xA1, 0xE5, 0},
{0xA2, 0x6B, 0},
{0xA3, 0x2B, 0},
{0xA1, 0xE3, 0},
};
const std::vector<MyConfig> m_Patch =
{
{0x01, 0x0F, 0},
{0x02, 0x0F, 0},
{0xA1, 0xFF, 0},
};
auto patch (std::vector<MyConfig> array,
const std::vector<MyConfig> &patch) -> std::vector<MyConfig> {
for (auto &o: array) {
for (const auto & p: patch) {
if (o.Addr == p.Addr) {
// Replace values with the same address
o = p;
}
}
}
return array;
}
} // namespace
int main() {
auto patched = patch(m_Original, m_Patch);
for (auto values: patched) {
std::cout << std::hex << values.Addr << ", " << values.Value << "\n";
}
}
Resulting output:
1, f
2, f
3, 54
1, f
a1, ff
a2, 6b
a3, 2b
a1, ff
If you want to change your original array (you dont, this is really bad practice) you do like this
const_cast<std::vector<MyConfig>&>(m_Original) = patch(m_Original, m_Patch);
If you want to unnest the loop and obfuscate it a bit, you can define some more functions like this (also not recommended)
auto patch (std::vector<MyConfig> array,
const std::vector<MyConfig> &patch) -> std::vector<MyConfig> {
auto replace_if_in_patch = [&patch] (auto &value) {
for (auto &p: patch) {
if (value.Addr == p.Addr) {
value = p;
return;
}
}
};
for (auto &o: array) {
replace_if_in_patch(o);
}
return array;
}
If you want a patch function that patches the incoming array, you might want to use references in the arguments
void patch (std::vector<MyConfig> array&,
// Notice change here -------------^
const std::vector<MyConfig> &patch) -> std::vector<MyConfig> {
for (auto &o: array) {
//...
// then remove the return statement
Upvotes: 2