Сортировка заархивированных (заблокированных) контейнеров в C ++ с использованием boost или STL
Что я хочу сделать: Я хочу отсортировать 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 для моей задачи (например, извлечь перестановки).
Что я попробовал: повышение :: zip_iterator а такжеповышение :: zip_range (с бустом :: объединить диапазон), но оба типа std :: sort иповышение :: Диапазон :: алгоритм :: сортировать жалуются, что итераторы / диапазоны только для чтения, а не произвольного доступа ...
Вопрос: Как отсортировать N векторов в шаге блокировки (в архиве)? Проблема выглядит довольно общей и общей, так что я думаю, должно быть простое решение с помощью, вероятно, очень сложной библиотеки, но я просто не могу ее найти ...
Примечания: да, в stackoverflow есть похожие вопросы, этот вопрос часто задают в разных формах. Однако они всегда закрыты с одним из следующих ответов:
Скопируйте ваши векторы в пару / кортеж и сортируйте этот кортеж ...Скопируйте ваши векторы в структуру с одним членом на вектор и сортируйте вектор структур ...Реализуйте свою собственную функцию сортировки для вашей конкретной проблемы ...Использовать вспомогательный массив индексов ...Используйте boost :: zip_iterator без примера или с примером, который дает плохие результаты.подсказки:
Я нашел эту тему вувеличить список рассылки что указывает на этобумага от Энтони Уильямса. Хотя кажется, что это работает только для пар, они также обсуждают TupleIteratorType, но я не смог его найти.user673679 нашелэто пост, содержащий хорошее решение для двух контейнеров. Это также решает проблему (акцент мой):[...] фундаментальная проблема заключается в том, что «пары» ссылок на массивы ведут себя не так, как должны [...] Я просто решил злоупотребить нотацией итератора и написать что-то, что работает. Это включало в себя написание несоответствующего итератора, гдессылка типа значения не совпадает с типом ссылки.
Ответ: см. комментарий от 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 (чего нет).