我正在实施以下数据集,并希望避免通常涉及的冗长的操作符号,例如.
和->
选择器等。
struct myList {
double node1 = 2,
node2 = 4,
node3 = 6.6,
node4 = 8
};
如何使用非特定选择任意求和节点。例如使用jQuery,如果这个结构是JSON,那么我可以这样做:
$(myList).children().each(function() {
sum += Number($(this).val());
});
// Or more generic, given size..
for (var i = 0; i < NUM_MEM; i++) {
sum += $(myList).nth-child(i).val();
}
答案 0 :(得分:3)
使用数组,向量(或列表)或地图,具体取决于最实用的内容。
数组不灵活,编译时固定大小。 std::vector<double>
灵活且易于使用。例如:
#include <iostream>
#include <numeric> // for std::accumulate, also look at <algorithms>
#include <vector>
struct data {
std::vector<double> nodes;
};
int main() {
data d = {{1, 2, 3}};
double sum = std::accumulate(std::begin(d.nodes), std::end(d.nodes), 0);
std::cout << "Total: " << sum << std::endl;
}
如果您希望使用名称而不是索引,请使用std::map<std::string, double>
(或std::unordered_map
)。
#include <iostream>
#include <map>
#include <numeric>
#include <string>
struct data {
std::map<std::string, double> items;
};
typedef std::map<std::string, double>::value_type my_map_element;
int main() {
data d = {{{"item1", 1}, {"item2", 2}, {"item3", 42}}};
double sum = std::accumulate(std::begin(d.items), std::end(d.items), 0,
[](double partial, my_map_element const& elt) {
return partial+elt.second;
});
//[](auto partial, auto const& elt) { // C++14
// return partial+elt.second;
//});
std::cout << "Total: " << sum << std::endl;
}
与大多数标准算法一样, std::accumulate
采用迭代器。你会发现通用C ++库中的所有地方。这使得算法非常灵活 - 它们不依赖于所使用的实际数据结构。
如果你不能改变数据类,你可以使用简单的包装器使它们可迭代(无论如何一次一种类型),使用std::reference_wrapper
时很容易使用{{3}},它的行为非常类似于引用,但可以存储在集合(和数组)中。
以下是一个如何运作的例子:
#include <functional> // for std::reference_wrapper
#include <iostream>
#include <numeric> // for std::accumulate
#include <vector>
struct data
{
double node1, node2, node3;
};
int main()
{
typedef std::vector<std::reference_wrapper<double>> double_wrapper;
data d { 1, 2, 3 };
double_wrapper helper = { d.node1, d.node2, d.node3 };
// You update via the helper or directly
d.node1 = 4;
helper[1].get() = 5; // will update d.node2
// Handy iteration
for (auto& node: helper)
node.get()++;
// And use standard algorithms
std::cout
<< "Sum: "
<< std::accumulate(std::begin(helper), std::end(helper), 0)
<< std::endl;
}
警告:辅助程序/包装器的生命周期与数据对象本身的生命周期密切相关。不要让包装器比数据对象更长。如果您在结构中“重新打包”外部数据和类似上面的向量供内部使用,出于同样的原因,也要非常小心复制(和移动)语义。
答案 1 :(得分:1)
只要保持所有类型相同,所有struct access说明符都相同,没有虚函数,所有类型都是离散类型,这可以通过标准来保证。
这是一个恐怖表演,但后来反省总是......
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
struct myList {
double node1 = 2,
node2 = 4,
node3 = 6.6,
node4 = 8,
myListEnd = -1;
const double* nthChild(size_t i) const {
return &node1 + i;
}
const double* begin() const {
return &node1;
}
const double* end() const {
return &myListEnd;
}
};
struct deref {
deref& operator+=(double a) {
_tot += a;
return *this;
}
operator double() const { return _tot; }
double _tot = 0;
};
deref operator+(deref d, double a) {
d += a;
return d;
}
using namespace std;
int main()
{
myList mine;
auto sum = accumulate(&mine.node1, &mine.myListEnd, deref());
cout << "sum is " << sum << endl;
sum = accumulate(mine.begin(), mine.end(), deref());
cout << "sum is " << sum << endl;
sum = accumulate(mine.nthChild(1), mine.nthChild(3), deref());
cout << "slice sum is " << sum << endl;
return 0;
}
输出:
Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
sum is 20.6
sum is 20.6
slice sum is 10.6