0

My requirement here is to merge the qty of both the sets if the price is same but isImplied bool are different.

Current Output:

Price : 100 IsImplied : 0 Qty :10

Price : 200 IsImplied : 0 Qty : 20

As the price 100 and 200 were already present in the set the insertion of p3 and p4 is ignored.

Desired output:

Price : 100 IsImplied : 0 Qty :40 (10 + 30) (Qty is merged as P1 and P3 have same price but different isImplied values)

Price : 200 IsImplied : 0 Qty : 60 (20 + 40) (Qty is merged as P2 and P4 have same price but different isImplied values)

class PriceLevel
{
public:
    int price;
    int qty;
    bool isImplied;

    PriceLevel(int _price, int _qty, bool _isImplied)
    {
        price = _price;
        qty = _qty;
        isImplied = _isImplied;
    }

    friend bool operator<(const PriceLevel &p, const PriceLevel &q);
};

bool operator<(const PriceLevel &p, const PriceLevel &q)
{
    if(p.price < q.price)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int main()
{
    std::set<PriceLevel> s1;

    PriceLevel p1(100,10, false);
    PriceLevel p2(200,20, false);
    PriceLevel p3(100,30, true);
    PriceLevel p4(200,40, true);

    s1.insert(p1);
    s1.insert(p2);
    s1.insert(p3);
    s1.insert(p4);

    set<PriceLevel>::iterator it = s1.begin();

    for(; it != s1.end(); it++)
    {
        cout << "Price: " << it->price << endl;

        cout << "Qty : " << it->qty << endl;

        cout << "IsImplied: " << it->isImplied << endl;

    }
}
CodeBeginner
  • 167
  • 1
  • 3
  • 11
  • and what is the problem with your current code? – bashrc Nov 02 '15 at 17:07
  • There is no problem with me current code syntactically. It does not take care of merging the two qty if IsImplied is different and the price are same. Basically I want to merge the qty if the price is same but IsImplied fields are different i.e if one is true and other is false. – CodeBeginner Nov 02 '15 at 17:10
  • What you will have to do is look up the price first. If it doesn't exist, insert it. If it does exist, compare the isImplied value to determine what to do. Question - what happens if isImplied is the same? – Anon Mail Nov 02 '15 at 17:11
  • If IsImplied is same, the new price an qty should be overwritten. – CodeBeginner Nov 02 '15 at 17:13

2 Answers2

2

If you need to retain the quantity as well, your compare function should use that information. set comparison works on strict weak ordering. There are two ways to achieve this. Pick the one that fits your design best.

1.Instead of keeping a set of PriceLevel itself, keep a map with the key as the Price and value as the quantity. Your update function will look something like:

void update(map<int, int> &valueMap, const PriceList &val)
{
    valueMap[val.price] += val.qty;    
}

` 2. Modify the insertion logic in your set. Update would look something like:

void update(set<PriceList> &valueMap, PriceList val)
{
    auto iter = valueMap.find(val);
    if (iter != valueMap.end())
    {
        val.qty = iter->qty + val.qty;
        valueMap.erase(iter);
    }
    valueMap.insert(val);
}

and obviously your compare function needs to be updated to account for qty. It should look something like

bool comp(const PriceList& val1, const PriceList& val2)
{
    return make_pair(val1.price, val1.qty) < make_pair(val2.price, val2.qty);
}
bashrc
  • 4,725
  • 1
  • 22
  • 49
0

You want to do something like like the following. Note we only do a single lookup.

// attempt to insert
std::pair<bool, std::set<PriceLevel>::iterator> result = s1.insert(p1);
if (result.first)  // insert did not work since element already existed
{
    PriceLevel & temp = *(result.second);
    if (temp.isImplied != p1.isImplied)
    {
        temp.qty += p1.qty;  // sum
    }
    else
    {
        temp.qty = p1.qty;  // overwrite
    }
}
// otherwise p1 didn't exist and was inserted
Anon Mail
  • 4,660
  • 1
  • 18
  • 21
  • No, it's just a code snippet meant to be illustrative. Apologies if there are errors. – Anon Mail Nov 02 '15 at 17:26
  • You can't overwrite anything is a `set` because it only provides `const` access. You have to remove and replace. It's not clear, but you seem to be trying to illustrate the contrary point. – Potatoswatter Nov 02 '15 at 17:32
  • … Please do not simply erase the answer, but edit it to clear up this confusion. – Potatoswatter Nov 02 '15 at 17:32
  • The OP has only the price as the "key" if you will. Everything else in the class does not participate in the "key" so it can be updated. I've only updated "non-key" member variables. Check out the signature of find - one of it's overloads returns an iterator, not a const_iterator. – Anon Mail Nov 02 '15 at 17:37
  • @AnonMail Check this http://stackoverflow.com/questions/908949/what-happens-when-you-modify-an-element-of-an-stdset – bashrc Nov 02 '15 at 17:39
  • @bashrc I just read it. I don't see any issue with my solution since I only update fields that don't participate in the key. – Anon Mail Nov 02 '15 at 17:43
  • @AnonMail It won't compile. The access is `const`, because `iterator` behaves just the same as `const_iterator`. You would quickly see this if you'd [tried to test it](http://coliru.stacked-crooked.com/a/2d023fb3d92f1f32). – Potatoswatter Nov 03 '15 at 01:51
  • According to this link: http://en.cppreference.com/w/cpp/container/set this is a C++11 difference. I suspect you are using a C++11 compiler. – Anon Mail Nov 03 '15 at 02:01
  • It's already late 2015. Obsolescent features are shaky ground regardless. [Clang](http://coliru.stacked-crooked.com/a/016f4aafafa5d4cc) and [GCC](http://coliru.stacked-crooked.com/a/f5a67cd9d57dabbe) behave the same in C++03 mode, which suggests that the change was retroactive (i.e. a Defect Report). – Potatoswatter Nov 04 '15 at 04:37