C++ 按列对表进行排序,同时保留行内容

Joe*_*ann 3 c++ sorting c++20

给定一个类型的行主表std::vector<std::vector<T>>(其中T是不太可比的类型,如intor std::string),我想按特定列对表进行排序,同时保留行内容(即一行只能作为一个整体移动,而不是单个细胞)。

例如,给定此表:

2 8 1 4
3 7 6 7
3 3 4 9
8 6 3 4
7 1 5 7
Run Code Online (Sandbox Code Playgroud)

按第三列(索引 2)排序,所需的结果将是:

2 8 1 4
8 6 3 4
3 3 4 9
7 1 5 7
3 7 6 7
Run Code Online (Sandbox Code Playgroud)

STL 实现这一目标的方法是什么?

我能想到的一种解决方案是将应排序的列复制到关联容器中(例如,std::unordered_map<T, std::size_t>键是单元格值,值是行索引),然后按键对映射进行排序(使用std::sort()),提取结果行索引顺序并使用它对原始表中的行重新排序。

然而,当将其编写为实际代码时,该解决方案似乎不优雅且相当冗长。

有哪些可能的、“好的”解决方案来实现这一点?

注意:表类型std::vector<std::vector<T>>是给定的,不能更改/修改。

Mik*_*CAT 7

使用比较器来比较要比较的元素。

std::vector<std::vector<T>> vec;
// add elements to vec
int idx = 2;
std::sort(vec.begin(), vec.end(), [idx](const std::vector<T>& a, const std::vector<T>& b) {
    return a.at(idx) < b.at(idx);
});
Run Code Online (Sandbox Code Playgroud)

完整的工作示例

#include <iostream>
#include <vector>
#include <algorithm>

typedef int T;

int main() {
    std::vector<std::vector<T>> vec = {
        {2, 8, 1, 4},
        {3, 7, 6, 7},
        {3, 3, 4, 9},
        {8, 6, 3, 4},
        {7, 1, 5, 7}
    };
    int idx = 2;
    std::sort(vec.begin(), vec.end(), [idx](const std::vector<T>& a, const std::vector<T>& b) {
        return a.at(idx) < b.at(idx);
    });
    for (size_t i = 0; i < vec.size(); i++) {
        for (size_t j = 0; j < vec[i].size(); j++) {
            std::cout << vec[i][j] << (j + 1 < vec[i].size() ? ' ' : '\n');
        }
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)


康桓瑋*_*康桓瑋 6

您可以通过使用 的自定义投影函数来完成此操作std::ranges::sort

#include <algorithm>
#include <vector>

int main() {
  std::vector<std::vector<int>> v{
    {2, 8, 1, 4},
    {3, 7, 6, 7},
    {3, 3, 4, 9},
    {8, 6, 3, 4},
    {7, 1, 5, 7}
  };
  
  int col = 2;
  std::ranges::sort(
    v, {}, [&col](auto& x) { return x[col]; }
  );
}
Run Code Online (Sandbox Code Playgroud)

演示