Se si deve continuare a utilizzare la struttura dati esistenti, che è essenzialmente un std::tuple
di tre std::vector
s, utilizzando boost::zip_iterator
sarebbe sembrano essere la strada da percorrere. A zip_iterator
tratta tre iteratori (da due a indici e uno a un valore) come una singola tupla ed è possibile utilizzare un oggetto funzione di confronto personalizzato per ordinare i dati sul posto. Purtroppo, boost::zip_iterator
non può essere utilizzato con std::sort
, come spiegato in this Q&A, perché non può essere scritto.
Ciò significa che è necessario scrivere la propria classe zip_iterator che può essere utilizzata con std::sort
. Si noti che non si tratta di un esercizio banale, vedere this Q&A e/o questo paper.
È molto più facile ordinare uno di un std::tuple
. Il mio tentativo qui sotto utilizza uno std::tuple
di due indici e un valore e memorizza tali voci in un std::vector
. Per l'ordinamento, utilizzo un lambda generico C++ 14 che inoltra i due indici in una tupla più piccola e li confronta lessicograficamente (vale a dire prima sull'indice di riga, quindi sull'indice di colonna) utilizzando la libreria operator<
di std::tuple
.
#include <algorithm>
#include <iostream>
#include <tuple>
#include <vector>
using index = uint32_t;
using value = float;
using sparse_entry = std::tuple<index, index, value>;
using sparse_matrix = std::vector<sparse_entry>;
int main()
{
// sparse 3x3 matrix
auto m = sparse_matrix {
std::make_tuple(1, 1, -2.2),
std::make_tuple(1, 0, 42 ),
std::make_tuple(0, 2, 3.4),
std::make_tuple(0, 1, 1.7)
};
// sort by row-index, then column-index
std::sort(begin(m), end(m), [](auto const& L, auto const& R) {
return
std::forward_as_tuple(std::get<0>(L), std::get<1>(L)) <
std::forward_as_tuple(std::get<0>(R), std::get<1>(R))
;
});
for (auto const& elem : m)
std::cout << "{ " << std::get<0>(elem) << ", " << std::get<1>(elem) << ", " << std::get<2>(elem) << "}, \n";
}
Live Example.
Se l'applicazione può utilizzare questo layout di dati trasformato (e potrebbero esserci motivi di prestazioni della cache per cui non può farlo), il codice precedente eseguirà l'ordinamento come desiderato.
NOTA: come cita @Casey, è anche possibile utilizzare al posto di std::tie
std::forward_as_tuple
, ma che possono fare molto quando si cambia sparse_entry
in una classe a tutti gli effetti definito dall'utente con getter ritorno per valore.
In breve, guarda la versione a 3 argomenti di 'std :: sort', quindi cerca' functor' o 'function object'. – PaulMcKenzie
Quindi è necessario dare una mano - se ti do due valori (i, j, k), dicci come determinare se il primo valore arriva prima del secondo valore. Anche quale forma è questa "tavola"? Devi dirci un po 'più in dettaglio su come sono strutturati questi dati. – PaulMcKenzie
Quindi vuoi ordinare tutti e tre gli array? Il più semplice sarebbe combinarli tutti in una 'struct' e avere una sola matrice di quel tipo. –