[英]Merge two std::sets
如果價格相同,我需要根據一個成員變量qty將兩個集合合並為結果集合。 在下面的示例中,我的結果集s3應該包含:
價格:100數量:40
價格:200數量:60
請注意,上述數量是當價格相同時兩組中的數量之和。
我的問題是如何構造下面的set 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;
}
}
如果您完全確定兩個源集包含的價格完全相同,則可以使用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++);
}
最好將它放在一個附加功能中。
如果您只需要兩個源集中都存在的結果集中的價格,則要簡單一些:
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;
}
}
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
(因為set
元素為const
),也可以對其進行修改。
如果不能使變量mutable
,則可以嘗試刪除現有的set元素,然后添加一個新的合並元素。
本質上,您試圖將集合用作映射並使用相等的鍵合並值。 您需要滾動自己的結果(更不用說它確實不建議...)。 這是一些讓您入門的東西。
#include <iostream>
#include <set>
using namespace std;
class PriceLevel
{
public:
int price;
int qty;
PriceLevel() {
price = 0;
qty = 0;
}
PriceLevel(int _price, int _qty)
{
price = _price;
qty = _qty;
}
friend bool operator<(const PriceLevel &p, const PriceLevel &q);
//Compares two PriceLevel objects and merges their values if their keys are the same.
//Return value is a std::pair that
//denotes if the compare was successful and the result is meaningful.
static std::pair<bool, PriceLevel> merge_equal(const PriceLevel& p, const PriceLevel& q) {
std::pair<bool, PriceLevel> result;
result.first = false;
if(p.price == q.price) {
result.first = true;
result.second.price = p.price;
result.second.qty = p.qty + q.qty;
}
return result;
}
};
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;
//Just in case...the world may explode otherwise.
if(s1.size() == s2.size()) {
for(const auto& pl1 : s1) {
for(const auto& pl2 : s2) {
//Only insert valid values.
auto r = PriceLevel::merge_equal(pl1, pl2);
if(r.first) s3.insert(r.second);
}
}
for(auto it = s3.begin(); it != s3.end(); it++) {
cout << "Price: " << it->price << endl;
cout << "Qty : " << it->qty << endl;
}
}
}
您只需兩行就可以合並兩個集合
#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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.