Classificação de containers zipados (bloqueados) em C ++ usando boost ou o STL
O que eu quero fazer: Eu quero ordenar 2, ou 3, ou N vetores, juntos,sem copiá-los em uma tupla. Ou seja, deixando a verbosidade de lado, algo como:
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;
Isso deve resultar:
5 55 555
4 44 444
...
1 11 111
Como estou fazendo agora: Eu implementei o meu próprio quicksort, onde o primeiro array que eu passo é usado para a comparação, e as permutações são aplicadas a todos os outros arrays. Eu simplesmente não consegui descobrir como reutilizar o std :: sort para o meu problema (por exemplo, permutações de extração).
O que eu tentei: boost :: zip_iterator eboost :: zip_range (com boost :: combine range), mas std :: sort eboost :: range :: algoritmo :: sort Reclamar que os iteradores / intervalos são somente leitura e não acesso aleatório ...
Questão: Como classifico N vetores na etapa de bloqueio (zipada)? O problema parece bastante genérico e comum, então eu acho que deve haver uma solução fácil através de uma biblioteca provavelmente muito complexa, mas eu simplesmente não consigo encontrá-lo ...
Observações: sim, existem questões semelhantes no stackoverflow, esta pergunta é feita muito em diferentes formas. No entanto, eles sempre são fechados com uma das seguintes respostas:
Copie seus vetores em um par / tupla e classifique essa tupla ...Copie seus vetores em uma estrutura com um membro por vetor e classifique um vetor de estruturas ...Implemente sua própria função de classificação para seu problema específico ...Use uma matriz auxiliar de índices ...Use boost :: zip_iterator sem um exemplo ou com um exemplo que produz resultados ruins.Dicas:
Eu encontrei este segmento noaumentar lista de discussão que aponta para issopapel de Anthony Williams. Embora isso pareça funcionar apenas para pares, eles também discusam um TupleIteratorType, mas não consegui encontrá-lo.user673679 encontradoisto post contendo uma boa solução para o caso de dois contêineres. Também fixa o problema (a ênfase é minha):[...] o problema fundamental é que "pares" de referências de matriz não se comportam como deveriam [...] eu simplesmente decidi abusar da notação de um iterador e escrever algo que funciona. Isso envolveu escrever, efetivamente, um iterador não-conformea referência do tipo de valor não é igual ao tipo de referência.
Responda: veja o comentário por interjay abaixo (isso também responde parcialmentepergunta futura):
#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;
}
Pergunta futura: a resposta anterior funciona para contêineres de seqüência. Poderíamos conseguir também trabalhar emclassificável recipientes (por exemplo, sequências e listas)? Isso exigiria random_access e TupleIterators bidirecionais, bem como um algoritmo de classificação que funciona em iteradores bidirecionais.
Atualizar: isso funciona para combinações de contêineres semelhantes a seqüência. No entanto, misturar uma lista exigiria que o std :: sort suportasse BidirectionalIterators (o que não é o caso).