我想要做什么:我想要将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
我现在的做法: 我实现了自己的快速排序算法,其中第一个数组用于比较,排列应用于所有其他数组。我只是无法想出如何重复使用std::sort来解决我的问题(例如提取排列)。
我尝试过的: boost::zip_iterator 和 boost::zip_range(使用boost::combine范围),但是std::sort和boost::range::algorithm::sort都抱怨迭代器/范围是只读而不是随机存取的...
问题: 如何同时对N个矢量进行锁定排序(zipped)?这个问题看起来非常通用和常见,所以我猜应该有一个简单的解决方案,虽然可能需要一个非常复杂的库,但我就是找不到它...
备注: 是的,在stackoverflow上有类似的问题,这个问题以不同的形式经常被提出。但是它们总是被以下答案之一关闭:
- 将您的向量复制到一个对/元组中,然后对该元组进行排序...
- 将您的向量复制到一个结构体中,每个向量都有一个成员,然后对结构体向量进行排序...
- 为您特定的问题实现自己的排序函数...
- 使用辅助索引数组...
- 使用boost::zip_iterator而没有示例或使用会产生错误结果的示例。
提示:
- 我在boost邮件列表中找到了这个主题,它指向了Anthony Williams的这篇文章。虽然这似乎只适用于一对,但他们也讨论了TupleIteratorType,但我还没有找到它。
- user673679发现了这篇帖子,其中包含两个容器情况的好解决方案,它还解决了问题(强调是我的):
#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;
}
未来问题: 上一个答案适用于序列容器。我们是否可以在可排序的容器(例如序列和列表)上实现这个功能?这将需要使用随机访问和双向元组迭代器以及能够在双向迭代器上工作的排序算法。
更新: 这适用于类似序列的容器的组合。但是混合使用列表将需要std::sort支持BidirectionalIterators(目前不支持)。
std::sort
如何通过std::iter_swap
重新排列元素:你的zip_iterator
应该支持这一点。 - pmrboost::zip_iterator
实现。 - gnzlbg