【发布时间】:2016-01-15 11:24:00
【问题描述】:
这是我从代码审查中得到的任务。我想根据一种特殊的比较谓词从一组中选择一个最小值。像这样:
struct Complex { ... };
float calcReduction(Complex elem);
Complex findMinValueWithPredicates(const std::vector<Complex>& values)
{
auto it = std::min_element(values.begin(), values.end(),
[](const Complex& a, const Complex& b) {
return calcReduction(a) < calcReduction(b);
});
if (it == values.end()) throw std::runtime_error("");
return *it;
}
在这里我找到基于谓词的最小元素。这个谓词计算两个值的 reduction 到 float,然后比较这些浮点数。效果很好,看起来很整洁。
你能看出问题吗?是的,对于一组 N 元素,calcReduction() 被称为 2N 次,而仅计算 N 次就足够了 - 每个元素一次。
解决此问题的一种方法是编写显式计算:
Complex findMinValueExplicit(const std::vector<Complex>& values)
{
float minReduction = std::numeric_limits<float>::max();
Complex minValue;
for (Complex value : values)
{
float reduction = calcReduction(value);
if (reduction < minReduction)
{
minReduction = reduction;
minValue = value;
}
}
if (minReduction == std::numeric_limits<float>::max()) throw std::runtime_error("");
return minValue;
}
它工作正常,我们只有N 调用calcReduction()。但是,与显式调用min_element 相比,它看起来过于冗长,意图也不是很清楚。因为当你调用min_element 时,很容易猜到你会找到一个最小元素,你知道的。
我现在唯一的想法是创建自己的算法,例如min_element_with_reduction,接受范围和归约函数。听起来很合理,但我想知道是否有现成的解决方案。
关于如何以明确的意图和一些现成的解决方案解决此任务的任何想法?欢迎提升。 C++17 和范围很有趣。
【问题讨论】:
-
为了简化代码,我首先检查
values.empty()。然后,用第一个元素初始化并进入剩余元素的循环。不,这可能不像您当前的代码那么明显,但是如果您优化此代码以获得最大速度(您已经对此进行了分析,对吗?)恕我直言,一些妥协是可以接受的,特别是如果结果代码在 cmets 中得到正确解释。 -
@UlrichEckhardt 我认为你是对的,唯一合理的做法是定义我自己的算法。其他解决方案看起来完全……复杂。
标签: c++ algorithm min c++17 range-v3