Честно говоря, ваш подход выглядит довольно сложным для меня. Большая часть его сложности связана с тем, что в вашем коде есть строки, но они присутствуют только неявно. Явное использование кода в коде не только помогает улучшить читаемость, но и облегчает написание кода.
Допустим, вы используете std::array<std::string,3>
для строк, тогда ваш код может быть таким же легковесным, как этот:
#include <vector>
#include <array>
#include <algorithm>
#include <iostream>
int main() {
using row_t = std::array<std::string,3>;
std::vector<row_t> vec = { {"1","8","1"},{"2","3","2"},{"3","5","5"},{"2","5","6"}};
std::sort(vec.begin(),vec.end(),[](const row_t& a, const row_t& b) { return a[2] < b[2]; });
for (const auto& row : vec) {
for (const auto& e : row) std::cout << e << " ";
std::cout << '\n';
}
}
Вывод:
1 8 1
2 3 2
3 5 5
2 5 6
ОК , это, вероятно, хороший подход к этой проблеме, и, возможно, это то, что я должен сделать, но я не могу потратить 2 месяца, чтобы изменить весь код ...
Вы могли бы сделать требования более ясно в вопросе. Я думаю, что если у вас есть 10 тыс. Строк кода, которые зависят от этой конкретной проблемы с использованием плоского вектора, когда другая структура данных будет более подходящей, тогда у вас будет большая проблема, чем как сортировать строки. Во всяком случае ...
Использование квартиры std::vector
обычно неплохая идея. Что мне не хватает в вашем коде, так это что-то вроде
template <int stride>
std::string& access_at(std::vector<std::string>& vec,size_t row,size_t col) {
return vec[ row * stride + col ];
}
template <int stride>
const std::string& access_at(const std::vector<std::string>& vec,size_t row,size_t col) {
return vec[ row * stride + col ];
}
. Это позволяет вам повторять таблицу следующим образом:
for (size_t i=0;i < vec.size()/3;++i) {
for (size_t j=0;j<3;++j) {
std::cout << access_at<3>(vec,i,j) << " ";
}
std::cout << '\n';
}
Далее я собираюсь бесстыдно украсть и изменить код из этот ответ . Основная идея c состоит в том, чтобы отсортировать вектор индексов вместо прямой сортировки вектора:
using index_t = std::vector<size_t>;
template <int stride>
index_t make_sorted_index(const std::vector<std::string>& values,size_t col) {
index_t index(values.size() / stride);
std::iota(index.begin(), index.end(), 0);
std::sort(index.begin(),
index.end(),
[&values,&col](size_t a, size_t b) {
return access_at<stride>(values,a,col) < access_at<stride>(values,b,col);
}
);
return index;
}
После того, как вы это получите, l oop для печати отсортированной таблицы потребуется лишь небольшая модификация:
for (size_t i=0;i < vec.size()/3;++i) {
for (size_t j=0;j<3;++j) {
std::cout << access_at<3>(vec,index[i],j) << " ";
}
std::cout << '\n';
}
Собираем все воедино:
#include <vector>
#include <numeric>
#include <algorithm>
#include <iostream>
template <int stride>
std::string& access_at(std::vector<std::string>& vec,size_t row,size_t col) { return vec[ row * stride + col ]; }
template <int stride>
const std::string& access_at(const std::vector<std::string>& vec,size_t row,size_t col) { return vec[ row * stride + col ]; }
using index_t = std::vector<size_t>;
template <int stride>
index_t make_sorted_index(const std::vector<std::string>& values,size_t col) {
index_t index(values.size() / stride);
std::iota(index.begin(), index.end(), 0);
std::sort(index.begin(),
index.end(),
[&values,&col](size_t a, size_t b) { return access_at<stride>(values,a,col) < access_at<stride>(values,b,col); }
);
return index;
}
int main() {
std::vector<std::string> vec = { "1","8","1","2","3","2","3","5","5","2","5","6"};
for (size_t i=0;i < vec.size()/3;++i) {
for (size_t j=0;j<3;++j) {
std::cout << access_at<3>(vec,i,j) << " ";
}
std::cout << '\n';
}
std::cout << '\n';
auto index = make_sorted_index<3>(vec,1);
for (size_t i=0;i < vec.size()/3;++i) {
for (size_t j=0;j<3;++j) {
std::cout << access_at<3>(vec,index[i],j) << " ";
}
std::cout << '\n';
}
}
С выводом:
1 8 1
2 3 2
3 5 5
2 5 6
2 3 2
3 5 5
2 5 6
1 8 1
Я оставлю это вам на самом деле скопировать вектор, чтобы получить отсортированный Во-первых, если вам это действительно нужно.
PS : В первой версии, приведенной выше, я сортировал по столбцу C, последняя часть сортируется по запросу B по запросу.
PPS : Я до сих пор не понимаю ваш код. Я не понимаю, почему у вас есть std::cout
внутри предиката, и, честно говоря, я понятия не имею, как ваш призыв к sort
должен достичь того, что вы хотите.