Unite elements that share the same value of a variable in a vector of structs

Viewed 45

For example, I have this struct :

struct Time
{
char Day[10];
int pay;
int earn;
}

And suppose that the vector of this Time struct has the following elements:

vector<Time> mySelf = ({"Monday", 20, 40}, {"Tuesday", 15, 20}, {"Monday", 30, 10}, {"Tuesday", 10, 5});

So is there any algorithm to unite the data so that elements with the same day name will appear once and the other variables of those elements will combine together to form a new vector like this :

vector<Time> mySelf = ({"Monday", 50, 50}, {"Tuesday", 25, 25});
1 Answers

You can try to insert your elements to unordered_map, and then reconstruct a vector. Search and insertion to the map have constant-time complexity, so all the operation will be O(n), because we need to iterate over a vector twice.

    std::unordered_map<std::string, Time> timeMap;
    for (const auto& t : mySelf)
    {
        if (timeMap.count(t.day) == 0)
        {
            timeMap[t.day] = t;
        }
        else
        {
            timeMap[t.day].pay += t.pay;
            timeMap[t.day].earn += t.earn;
        }
    }

or shorter version, since insert already checks if the element exists and will not overwrite it:

    for (const auto& t : mySelf)
    {
        timeMap.insert({t.day, {t.day,0,0}});
        timeMap[t.day].pay += t.pay;
        timeMap[t.day].earn += t.earn;
    }

and then the vector reconstruction:

    std::vector<Time> result;
    result.reserve(timeMap.size());
    for (const auto&[key, val] : timeMap)
    {
        result.push_back(val);
    }

Alternatively you could use std::unordered_set but then you need some hash function for your struct. Probably you could improve it further with move semantics.

live demo

Related