【发布时间】:2022-11-10 01:34:01
【问题描述】:
我有一个具有非常相似的重复代码的函数。我喜欢重构它,但不想要任何复杂的映射代码。
该代码基本上过滤掉表中的列。我通过让比较语句具有简单类型使这个示例变得简单,但真正的比较可能更复杂。
我希望可能有一些模板或 lambda 技术可以做到这一点。
vector<MyRecord*>& MyDb::Find(bool* field1, std::string * field2, int* field3)
{
std::vector<MyRecord*>::iterator iter;
filterList_.clear();
std::copy(list_.begin(), list_.end(), back_inserter(filterList_));
if (field1)
{
iter = filterList_.begin();
while (iter != filterList_.end())
{
MyRecord* rec = *iter;
if (rec->field1 != *field1)
{
filterList_.erase(iter);
continue;
}
iter++;
}
}
if (field2)
{
iter = filterList_.begin();
while (iter != filterList_.end())
{
MyRecord* rec = *iter;
if (rec->field2 != *field2)
{
filterList_.erase(iter);
continue;
}
iter++;
}
}
if (field3)
{
iter = filterList_.begin();
while (iter != filterList_.end())
{
MyRecord* rec = *iter;
if (rec->field3 != *field3)
{
filterList_.erase(iter);
continue;
}
iter++;
}
}
return filterList_;
}
更新: 以防万一有人好奇,这是我的最终代码。再次感谢大家。很容易理解和维护。
vector<MyRecord*>& MyDb::Find(bool* field1, std::string* field2, int* field3)
{
auto compare = [&](MyRecord* rec) {
bool add = true;
if (field1 && rec->field1 != *field1) {
add = false;
}
if (field2 && rec->field2 != *field2) {
add = false;
}
if (field3 && rec->field3 != *field3) {
add = false;
}
return add;
};
filterList_.clear();
std::copy_if(list_.begin(), list_.end(), back_inserter(filterList_), compare);
return filterList_;
}
【问题讨论】:
-
if ((field1 && rec->field1 != *field1)) || (field2 && rec->field2 != *field2) || (field3 && rec->field3 != *field3) { ...}。预先删除if (field1)和其他检查,运行循环一次,同时检查所有三个字段。 -
只是建议-而不是创建完整副本然后删除元素,我只会将原始列表中需要的元素复制到过滤后的元素中
-
@IgorTandetnik 就像我说的那样,我使这个示例变得简单,实际代码比这多列和不同的数据类型。我想避免有一个巨大的 if 语句。无论如何,我可能最终会这样做。
-
如果模板/lambda 失败,您总是可以求助于使用宏
-
我相信是这样。所有列都是可选的。
标签: c++ algorithm templates refactoring c++-standard-library