考虑以下C ++程序,在给定数字向量的情况下打印最小的相邻差异:
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
int main()
{
std::vector<int> numbers = { 10, 1, 43, 59, 78, 46, 63, 12 };
std::vector<int> deltas;
std::adjacent_difference( numbers.begin(),
numbers.end(),
std::back_inserter( deltas ) );
auto minEl = std::min_element( deltas.begin() + 1,
deltas.end() );
std::cout << *minEl;
}
我想摆脱中间deltas
向量,但仍然继续使用std::adjacent_difference
和std::min_element
(而不是自己循环)。
在函数式语言中,中间数据结构的表达通常称为deforestation(或“融合”)。在C ++中有同样的方法吗?
我想有可能设计某种迭代器包装器,它允许递增地计算相邻差异,因为min_element
迭代范围。我在标准库中找不到类似的东西。也许某些第三方库(Boost?)提供类似的东西?
答案 0 :(得分:1)
我猜测(并且希望)你会得到一些更好的答案,但如果你足够热衷于充实一些辅助代码库,那么这就是一种方法: / p>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
#include <algorithm>
template <typename T>
struct min
{
typedef T element_type;
min(int& min) : min_(min) { }
min& operator *() { return *this; }
min& operator=(const T& t)
{
if (first_)
min_ = t, first_ = false;
else if (t < min_)
min_ = t;
}
min& operator++() { return *this; }
bool first_ = true;
T& min_;
};
template <typename Iterator>
struct skip_take // i.e. skip some elements, take some elements...
{
skip_take(Iterator i, size_t skip, size_t take = size_t(-1))
: i_(i), skip_(skip), take_(take)
{ }
skip_take& operator *() { return *this; }
skip_take& operator=(const typename Iterator::element_type& t)
{ if (skip_ == 0 && take_) *i_ = t; }
skip_take& operator++()
{ if (skip_) --skip_; else if (take_) --take_, ++i_; return *this; }
Iterator& i_;
size_t skip_, take_;
};
int main()
{
std::vector<int> numbers = { 10, 1, 43, 59, 78, 46, 63, 12 };
int result;
std::adjacent_difference(numbers.begin(), numbers.end(),
skip_take<min<int>>(min<int>(result), 1));
std::cout << result << '\n';
}
(ideone.com上的代码)
更一般地说,C ++缺少协同程序(许多其他语言中的懒惰生成器使用它们)对此类事情的良好实现感到沮丧 - 有一个提升库或提议浮动 - 不确定有多可用),以及标准库对范围内迭代器的偏好(使得一个算法更难以返回下一个算法应该操作的范围)。有很多&#34;功能性&#34;使用模板表达式和其他技术的C ++库比上面的代码复杂得多,效果很好。
答案 1 :(得分:1)
从技术上讲,您可以编写自己的类来提供输出迭代器。然后,您可以覆盖取消引用和增量运算符以执行所需的计算。这是一个黑客,可能只是编写afor循环是最好的解决方案。
#include <vector>
#include <iostream>
#include <numeric>
using namespace std;
class Something;
struct SomethingIter {
SomethingIter(Something* p) : parent(p) {};
SomethingIter& operator++();
int& operator* ();
private:
Something* parent;
};
class Something {
public:
Something() : minset(false), first(true), min(0) { }
SomethingIter storage() {
SomethingIter ret(this);
return ret;
}
void set() {
if (first) { first = false; }
else if (!minset || s < min) {
min = s;
minset = true;
}
}
int& value() { return s; }
int getMin() const { return min; }
private:
bool first;
bool minset;
int min;
int s;
};
SomethingIter& SomethingIter::operator++() {
parent->set();
return *this;
}
int& SomethingIter::operator* () {
return parent->value();
}
int main() {
Something s;
vector<int> values{ 0, 2, 5 };
adjacent_difference(values.begin(), values.end(), s.storage());
cout << "min: " << s.getMin() << endl;
return 0;
}
但为什么会让事情复杂化?
第一个用例:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int minDiff(const vector<int>& values) {
size_t len = values.size();
if (len < 2) { throw runtime_error("Invalid vector"); }
int mindiff = values[1] - values[0];
for (size_t i = 2; i<len; ++i) {
int diff = values[i] - values[i-1];
if (diff < mindiff) { mindiff = diff; }
}
return mindiff;
}
int main() {
vector<int> values{0, 2, 5};
cout << minDiff(values) << endl;
return 0;
}
第二个用例:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main() {
vector<string> A{"AB", "BA", "AAA"};
unsigned int sum = 0;
for_each (A.begin(), A.end(), [&sum](const string& s) {
if (s[0] == 'A') { sum += s.length(); } });
cout << sum << endl;
return 0;
}