std::set<T>
容器如何检查两个对象是否唯一?我尝试重写等于运算符(==),但它没有用。
我想这样做的原因是我让我们说一个人类,我指定我的人是同一个人,如果他们有相同的名字(甚至可能是生日,地址等)。
在ccpreference.com中,他们写下以下内容(我有点不清楚):
标准库的每个地方都使用比较概念,唯一性 通过使用等价关系来确定。不精确的说, 两个对象a和b被认为是等价的(不唯一),如果两者都不相同 比较少:!comp(a,b)&amp;&amp; !comp(b,a)。
我认为,这个问题也扩展到其他STL容器甚至算法(甚至可能扩展到整个STL)。因此,如果将来我想使用函数std::find
,我会查找人的名字而不是对象本身。这是对的吗?
我想添加一些示例代码。
// My operator overloading comparing two strings.
bool operator==(Node & rhs) const {
return this->name.compare(rhs.name);
}
然后,在UnitTest中,我将两个具有相同名称的对象添加到集合中。它被添加两次(但根据operator==
应该是相同的。
void test_adding_two_identical_nodes() {
// The pool is a set<Node> inside
model::Node_Pool pool{};
pool.store_node(model::Node{"Peter"});
pool.store_node(model::Node{"Peter"});
// Should be only 1 because the same node should be added once into a set.
ASSERT_EQUAL(1, pool.size());
}
答案 0 :(得分:3)
import UIKit
class Order {
var stations = [Station]()
var companies = [String]()
}
class Station {
let name: String
let amount: Int
init(name: String, amount: Int) {
self.name = name
self.amount = amount
}
}
class TableViewController: UITableViewController {
var orders = [Order]()
override func viewDidLoad() {
super.viewDidLoad()
tableView!.rowHeight = UITableViewAutomaticDimension
tableView!.estimatedRowHeight = 44.0
//simulated data
let order1 = Order()
order1.companies.append("Global @ CITGO Braintree, Braintree")
order1.companies.append("Exxon @ Global, Chelsea")
order1.stations.append(Station(name: "Tyngsboro Mobil #2871", amount: 4000))
order1.stations.append(Station(name: "Grafton St #10095", amount: 15000))
orders.append(order1)
let order2 = Order()
order2.companies.append("Exxon @ Global, Chelsea")
order2.stations.append(Station(name: "Winstead Citgo #2001", amount: 3000))
orders.append(order2)
let order3 = Order()
order3.companies.append("MSCG @ Sunoco Partners")
order3.stations.append(Station(name: "Citgo #123", amount: 7000))
order3.stations.append(Station(name: "Mobil #345", amount: 12500))
order3.stations.append(Station(name: "Exxon #567", amount: 300))
order3.stations.append(Station(name: "Citgo #789", amount: 6100))
order3.stations.append(Station(name: "Stoughton Mobil #2744", amount: 9098))
order3.stations.append(Station(name: "Westborough Mobil #2720", amount: 120000))
orders.append(order3)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return orders.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as! TableViewCell
let order = orders[indexPath.row]
cell.companyLabel.text = ""
for (index, company) in order.companies.enumerated() {
cell.companyLabel.text! += company
if index < order.companies.count - 1 {
cell.companyLabel.text! += "\n"
}
}
for station in order.stations {
// create horizontal stack view to arrange the station name and amount
let horizontalStackView = UIStackView()
horizontalStackView.axis = .horizontal
let nameLabel = UILabel()
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.text = station.name
horizontalStackView.addArrangedSubview(nameLabel)
let amountLabel = UILabel()
amountLabel.translatesAutoresizingMaskIntoConstraints = false
amountLabel.addConstraint(NSLayoutConstraint(item: amountLabel, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: 60))
amountLabel.backgroundColor = UIColor.purple
amountLabel.textAlignment = .right
amountLabel.textColor = UIColor.white
amountLabel.text = String(station.amount)
horizontalStackView.addArrangedSubview(amountLabel)
// add the horizontal stack view to the vertical stack view containing all stations
cell.stackView.addArrangedSubview(horizontalStackView)
}
return cell
}
无法使用std::set<T>
进行比较。默认情况下,它使用==
进行比较。反过来,std::less<T>
默认使用运算符std::less<T>
。
实现集合的一种方法是覆盖<
,如下所示:
operator<
或者,可以在声明#include <set>
#include <cassert>
struct Person {
const char *name;
int uid;
};
bool operator<(const Person& a, const Person& b) {
return a.uid < b.uid;
}
int main () {
Person joe = {"joseph", 1};
Person bob = {"robert", 2};
Person rob = {"robert", 3};
Person sue = {"susan", 4};
std::set<Person> people;
people.insert(joe);
people.insert(bob);
people.insert(rob);
assert(people.count(joe) == 1);
assert(people.count(bob) == 1);
assert(people.count(rob) == 1);
assert(people.count(sue) == 0);
Person anonymous_3 = {"", 3};
assert( std::strcmp(people.find(anonymous_3)->name, "robert") == 0);
}
时将比较运算符作为模板参数传递。在上面的示例中,这可能是比较运算符:
set
struct Person_Compare {
bool operator()(const Person& a, const Person& b) const {
return a.uid < b.uid;
}
};
声明可能如下所示:
std::set
示例的其余部分未更改。
答案 1 :(得分:0)
首先,不要覆盖比较运算符来比较除TOTAL等价之外的任何东西。否则你最终会遇到维护噩梦。
那就是说,你要覆盖operator <
。您应该改为设置比较器类型。
struct compare_people : std::binary_function<person,person,bool>
{
bool operator () ( person const& a, person const& b) const { return a.name() < b.name();
};
std::set<person, compare_people> my_set;