假设传入的序列已排序,您可以简单地使用std::distance 计算长度并在开始和结束处跳过适当数量的元素:
编辑: 将std::accumulate 用于随机访问迭代器的扩展代码;如果允许使用 C++20 功能,请使用概念而不是区分迭代器类型和附加参数。
template<typename RandomAccessIterator>
double truncated_mean_impl(RandomAccessIterator begin, RandomAccessIterator end, double trimming_fraction, std::random_access_iterator_tag)
{
if (trimming_fraction < 0)
{
throw std::range_error("trimming_fraction must not be negative");
}
if(trimming_fraction >= 0.5)
{
return std::numeric_limits<double>::quiet_NaN(); // no elements left after trimming
}
auto const count = std::distance(begin, end);
auto const skippedElementCountFront = static_cast<decltype(count)>(count * trimming_fraction);
auto const summandCount = count - 2 * skippedElementCountFront;
return std::accumulate<RandomAccessIterator, double>(begin + skippedElementCountFront, end - skippedElementCountFront, 0) / summandCount;
}
template<typename ForwardIterator>
double truncated_mean_impl(ForwardIterator begin, ForwardIterator end, double trimming_fraction, std::forward_iterator_tag)
{
if (trimming_fraction < 0)
{
throw std::range_error("trimming_fraction must not be negative");
}
if(trimming_fraction >= 0.5)
{
return std::numeric_limits<double>::quiet_NaN(); // no elements left after trimming
}
auto const count = std::distance(begin, end);
auto const skippedElementCountFront = static_cast<decltype(count)>(count * trimming_fraction);
// skip elements in the front
for (auto i = skippedElementCountFront; i != 0; --i, ++begin) {}
auto const summandCount = count - 2 * skippedElementCountFront;
double sum = 0;
for (auto i = summandCount; i != 0; --i, ++begin)
{
sum += *begin;
}
return sum / summandCount;
}
template<typename ForwardIterator>
double truncated_mean(ForwardIterator begin, ForwardIterator end, double trimming_fraction)
{
return truncated_mean_impl<ForwardIterator>(begin, end, trimming_fraction, typename std::iterator_traits<ForwardIterator>::iterator_category());
}
int main()
{
std::vector<int> const values { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::cout << truncated_mean(values.cbegin(), values.cend(), 0.1) << '\n';
}
如果输入序列未排序,并且您不能或不想对输入进行排序,则将元素复制到新向量并将原始算法应用于该向量可能是最好的。