合并两个std :: sets

时间:2015-11-03 02:10:03

标签: c++ stl

如果价格相同,我需要根据一个成员变量qty将两个集合并到一个结果集中。在下面的例子中,我的结果集s3应该包含:

价格:100 数量:40

价格:200 数量:60

请注意,上面的数量是价格相同时两个数量的总和。

我的问题是我如何构建下面的集合s3:

请指导我。

#include <set>
#include <iostream>

using namespace std;

class PriceLevel
{
public:
    int price;
    int qty;

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

    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;
    std::set<PriceLevel> s2;

    PriceLevel p1(100,10);
    PriceLevel p2(200,20);

    PriceLevel p3(100,30);
    PriceLevel p4(200,40);

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

    s2.insert(p3);
    s2.insert(p4);

    std::set<PriceLevel> s3;

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

    // How should I Initialize s3

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

4 个答案:

答案 0 :(得分:2)

如果您完全确定两个源集包含的价格完全相同,则可以使用std::transform的二进制版本。

如果它们可能包含不相等的数据,您必须手动执行此操作,如下所示:

std::set<PriceLevel> s3;

// How should I Initialize s3
std::set<PriceLevel>::iterator 
    first1 = s1.begin(),
    last1 = s1.end(),
    first2 = s2.begin(),
    last2 = s2.end();
while (first1 != last1 && first2 != last2) {
    if (first1->price < first2->price) {        
        s3.insert(*first1++);
    }
    else if (first1->price > first2->price) {
        s3.insert(*first2++);
    }
    else {
        s3.insert(PriceLevel(first1->price, first1->qty + first2->qty));
        ++first1;
        ++first2;
    }
}
while (first1 != last1) {
     s3.insert(*first1++);
}
while (first2 != last2) {
     s3.insert(*first2++);
}

这最好放在额外的功能中。

View on IdeOne

如果需要两个源集中存在的结果集中的那些价格,那就更简单了:

while (first1 != last1 && first2 != last2) {
    if (first1->price < first2->price) {        
        ++first1;
    }
    else if (first1->price > first2->price) {
        ++first2;
    }
    else {
        s3.insert(PriceLevel(first1->price, first1->qty + first2->qty));
        ++first1;
        ++first2;
    }
}

答案 1 :(得分:1)

set不适合您的应用程序数据结构。请考虑使用map<int, int>代替:

map<int, int> p1, p2, p3; // map price -> quantity

p1[100] = 10;
p1[200] = 20;

p2[100] = 30;
p2[200] = 40;

p3 = p1;
for(auto &i : p2) {
    p3[i.first] += i.second;
}

// Now p3[100]=40 and p3[200]=60.

您还可以set使用map类似set::find

s3 = s1;
for(auto &i : s2) {
    auto it = s3.find(i);
    if(it == s3.end()) {
        s3.insert(i);
    } else {
        it->qty += i.qty;
    }
}

要实现此目的,您必须将qty声明为mutable int,以便即使PriceLevel结构为const也可以修改它(因为元素一个setconst)。

如果您无法生成变​​量mutable,则可以尝试删除现有的set元素,然后添加新的合并元素。

答案 2 :(得分:1)

您实际上是在尝试将一个集合用作地图并使用相等的键合并值。你需要推出自己的结果(更不用说它真的不可取......)。这是让你入门的东西。

var Horseman = require("/usr/local/lib/node_modules/node-horseman");
var horseman = new Horseman();

function horseFunction(){
    console.log("inside horseFunction");
    var hasButton = horseman.exists("input[name='btnK']");
    console.log(hasButton) //prints the promise
    return hasButton;
}


horseman
    .userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0")
    .open("https://www.google.com/")
    .waitForNextPage()
    .log("just opened google")
    .then( horseFunction )
    .log() //prints the result of horseman.exists("input[name='btnK']")
    .finally(function(){
        console.log("Finish!")
        horseman.close();
    });

//};

答案 3 :(得分:1)

你可以只用两行合并两套

#include <set>

template <typename _Ty>
std::set<_Ty> merge(const std::set<_Ty> &x, const std::set<_Ty> &y) const
{
    std::set<_Ty> merged = x; //initial merged set from x
    merged.insert(y.begin(), y.end()); //add contents of y to merged

    return move(merged);
}