我想做什么: 我想对锁定在一起的2个,3个或N个向量进行排序, 而无需将它们复制 到元组中。也就是说,将冗长性放在一边,类似于:
vector<int> v1 = { 1, 2, 3, 4, 5}; vector<double> v2 = { 11, 22, 33, 44, 55}; vector<long> v3 = {111, 222, 333, 444, 555}; typedef tuple<int&,double&,long&> tup_t; sort(zip(v1,v2,v3),[](tup_t t1, tup_t t2){ return t1.get<0>() > t2.get<0>(); }); for(auto& t : zip(v1,v2,v3)) cout << t.get<0>() << " " << t.get<1>() << " " << t.get<2>() << endl;
这应该输出:
5 55 555 4 44 444 ... 1 11 111
我现在的操作方式: 我实现了自己的quicksort,将我传递的第一个数组用于比较,并将排列应用于所有其他数组。我只是不知道如何为我的问题重用std :: sort(例如,提取排列)。
我 尝试了 什么: boost ::zip_iterator和boost::zip_range(带有boost:: combine range),但是std :: sort和boost :: range :: algorithm :: sort都抱怨迭代器/范围是只读的而不是随机访问…
问题: 如何在锁定步骤(压缩)中对N个向量进行排序?这个问题看起来很普通而且很常见,所以我想必须通过一个可能非常复杂的库找到一个简单的解决方案,但是我只是找不到它…
备注: 是的,中也有类似的问题,这个问题经常以不同的形式被问到。但是,它们始终使用以下答案之一关闭:
提示:
根本的问题是数组引用的“成对”的行为不像它们应该表现的那样,我只是简单地决定滥用迭代器的符号并编写有效的东西。这涉及有效地编写一个不一致的迭代器,其中 值类型的引用与引用类型不同。
答: 请参阅下面的interjay评论 (这也部分回答了 未来的问题 ):
#include "tupleit.hh" #include <vector> #include <iostream> #include <boost/range.hpp> #include <boost/range/algorithm/sort.hpp> #include <boost/range/algorithm/for_each.hpp> template <typename... T> auto zip(T&... containers) -> boost::iterator_range<decltype(iterators::makeTupleIterator(std::begin(containers)...))> { return boost::make_iterator_range(iterators::makeTupleIterator(std::begin(containers)...), iterators::makeTupleIterator(std::end(containers)...)); } int main() { typedef boost::tuple<int&,double&,long&> tup_t; std::vector<int> a = { 1, 2, 3, 4 }; std::vector<double> b = { 11, 22, 33, 44 }; std::vector<long> c = { 111, 222, 333, 444 }; auto print = [](tup_t t){ std::cout << t.get<0>() << " " << t.get<1>() << " " << t.get<2>() << std::endl; }; boost::for_each( zip(a, b, c), print); boost::sort( zip(a, b, c), [](tup_t i, tup_t j){ return i.get<0>() > j.get<0>(); }); for ( auto tup : zip(a, b, c) ) print(tup); return 0; }
未来的问题: 先前的答案适用于序列容器。我们还能在 可排序的 容器(例如序列和列表)上工作吗?这将需要random_access和双向TupleIterators,以及在双向迭代器上工作的排序算法。
更新: 这适用于类似序列的容器的组合。但是,混合列表将需要std :: sort支持BidirectionalIterators(不需要)。
这是一个基于 range-v3 库的工作示例,该库已提出标准化要求
#include <range/v3/all.hpp> #include <iostream> using namespace ranges; int main() { std::vector<int> a1{15, 7, 3, 5}; std::vector<int> a2{ 1, 2, 6, 21}; sort(view::zip(a1, a2), std::less<>{}, &std::pair<int, int>::first); std::cout << view::all(a1) << '\n'; std::cout << view::all(a2) << '\n'; }