Ivan
Ivan

Reputation: 1455

Optimal way to replace values in Array

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:

  1. Just create a new array with the needed values (but then I'm allocating a big array that I will never use.

  2. 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

Answers (1)

Lasersköld
Lasersköld

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

Related Questions