我有一个 obj
对象列表,每个对象都有一个 eval()
方法,返回一个 double
。我想获得所有这些的最大值。到目前为止,我一直都是这样做的
double maxval = std::numeric_limits<double>::lowest();
for (const auto &obj: objs) {
maxval = std::max(maxval, obj->eval());
}
我想知道是否有更优雅的解决方案,您不必设置初始值-inf,类似于 Python 的
max_value = max(obj.eval() for obj in objs)
也许吧。请注意 eval()
可能很昂贵,所以我只想为每个 obj
eval()
一次。
有什么提示吗?可读性加分。
最佳答案
一些 <ranges>
好东西(仅限 C++20):
#include <ranges>
const auto maxval = std::ranges::max_element(objs, std::less<>{}, &ObjType::eval);
if (maxval != objs.cend())
doStuffWith(*maxval);
哪里ObjType
是序列元素的类型。最后一次检查也可能是关于容器的大小 maxval
当序列不为空时,肯定是一个可取消引用的迭代器,例如
if (!objs.empty()) ; // ...
但是请注意,正如@NathanOliver 指出的那样,这会调用 eval()
2N-2次。这是一个自定义模板,将调用 eval()
恰好 N 次:
#include <optional>
#include <functional>
#include <type_traits>
template <class Range, class Cmp = std::less<>, class Proj = std::identity>
auto maxValue(const Range& rng, Cmp pred = Cmp{}, Proj p = Proj{})
{
using std::begin;
using std::end;
using ValueType = std::remove_cvref_t<std::invoke_result_t<Proj,
decltype(*begin(rng))>>;
auto first = begin(rng);
const auto last = end(rng);
if (first == last)
return std::optional<ValueType>{};
auto result = std::invoke(p, *first);
for (++first; first != last; ++first)
result = std::max(std::invoke(p, *first), result, pred);
return std::optional{result};
}
它不返回迭代器,而是返回结果值 - 包装到 std::optional
中如果范围为空(则结果为 std::nullopt
)。类型的用法 Test
具有成员函数 Test::eval()
会是这样的:
const auto max = maxValue(myContainer, std::less<>{}, &Test::eval);
第二个和第三个参数具有合理的默认值,因此对于原始类型等,它们可以被忽略。
关于c++ - 通过函数调用在 C++ 数组上取最大值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67838347/