大POD作为元组进行排序
Large POD as tuple for sorting
我有一个POD,大约有30个不同类型的成员,我想在一个容器中存储数千个POD,然后按其中一个成员对该容器进行排序。
例如: struct Person{
int idNumber;
....many other members
}
我想按idNumber
或我选择排序的任何其他成员排序的数千个Person
对象。
我今天已经研究了一段时间,似乎最有效的,或者至少,最简单的解决方案是根本不使用struct
,而是使用tuple
,我可以将索引号传递给自定义比较函子,以便在std::sort
中使用。(本页的一个示例展示了一种容易实现这种类型排序的方法,但它是在struct
的单个成员上实现的,这将使模板化不那么容易,因为您必须通过名称引用成员,而不是通过tuple
提供的索引。)
关于这种方法,我的问题分为两个部分:1)一个元组相当大,有几十个成员,这是可以接受的吗?2)是否有一个同样优雅的解决方案,继续使用struct
而不是tuple
?
您可以创建一个比较器,它在内部存储一个指向成员的指针,以便它知道使用哪个成员进行比较:
struct POD {
int i;
char c;
float f;
long l;
double d;
short s;
};
template<typename C, typename T>
struct Comp {
explicit Comp(T C::* p) : ptr(p) {}
bool operator()(const POD& p1, const POD& p2) const
{
return p1.*ptr < p2.*ptr;
}
private:
T C::* ptr;
};
// helper function to make a comparator easily
template<typename C, typename T>
Comp<C,T> make_comp( T C::* p)
{
return Comp<C,T>(p);
}
int main()
{
std::vector<POD> v;
std::sort(v.begin(), v.end(), make_comp(&POD::i));
std::sort(v.begin(), v.end(), make_comp(&POD::d));
// etc...
}
为了进一步推广这一点,让make_comp
使用一个自定义比较器,这样您就可以进行大于和其他比较。
1)是否可以接受一个相当大的元组,有几十个成员?
可以接受。然而,它并不容易维护,因为您需要处理的只是元组中的索引,这非常类似于一个神奇的数字。您所能得到的最好结果是使用enum
重新引入名称到索引的映射,这也很难维护。
2)是否有一个同样优雅的解决方案,继续使用结构体而不是元组?
你可以很容易地写一个模板函数来访问一个特定的结构体成员(公平地说,我没有花太多的精力在这上面,它更多的是一个概念的证明,而不是其他的,所以你知道它是如何做到的):
template<typename T, typename R, R T::* M>
R get_member(T& o) {
return o.*M;
}
struct Foo {
int i;
bool j;
float k;
};
int main() {
Foo f = { 3, true, 3.14 };
std::cout << get_member<Foo, float, &Foo::k>(f) << std::endl;
return 0;
}
从这里开始,编写一个通用比较器就很容易了,您可以在闲暇时使用它(我将把它作为练习留给您)。这样,您仍然可以按名称引用成员,但不需要为每个成员编写单独的比较器。
您可以使用模板来提取排序键:
struct A
{
std::string name;
int a, b;
};
template<class Struct, typename T, T Struct::*Member>
struct compare_member
{
bool operator()(const Struct& lh, const Struct& rh)
{
return lh.*Member < rh.*Member;
}
};
int main()
{
std::vector<A> values;
std::sort(begin(values), end(values), compare_member<A, int, &A::a>());
}
也许你想看看boost::multi_index_container,这是一个非常强大的容器,如果你想按不同的键索引(排序)对象。
创建一个类,该类可以使用指向Person
成员数据的指针进行比较:
std::sort(container.begin(), container.end(), Compare(&Person::idNumber));
其中Compare
为:
template<typename PointerToMemberData>
struct Compare {
Compare(PointerToMemberData pointerToMemberData) :
pointerToMemberData(pointerToMemberData) {
}
template<typename Type
bool operator()(Type lhs, Type rhs) {
return lhs.*pointerToMemberData < rhs.*pointerToMemberData
}
PointerToMemberData pointerToMemberData;
};
- C++:TypeDef使用元组
- Pybind11:将元组列表从Python传递到C++
- 重载元组索引运算符-C++
- 在C++中,如何通过几种类型从元组中选择多个元素
- C++ 按数值对元组<字符串、浮点数>然后按字典顺序排序的向量
- 如何构造元组向量并像配对一样对它们进行排序?
- 编译时排序的异构元组
- 如何对两个容器元组进行排序?
- 元组上的推力排序非常慢
- 基于元组值对向量进行排序
- 按固定组件对元组容器进行排序
- 比较具有替代排序的自定义类型的std::元组(或std::对).是否可以插入自定义的小于/比较函数
- 对boost元组的数据进行排序
- 使用精神::业力从元组的向量制作重新排序的元组
- 大POD作为元组进行排序
- 如何任意对元组的类型进行排序?
- 如何使用现有的整数排序来排序整数元组
- 元组是如何自动排序的
- 自定义对元组向量进行排序
- 自定义排序元组向量时出错