You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Views实现基于数据的索引排序?

用C++20 Ranges实现无自定义谓词的索引排序与多索引绑定

核心思路

利用C++20的std::ranges::sort结合**投影(projection)**特性,直接通过索引映射到对应的值完成排序,完全无需自定义谓词。投影函数会把索引数组中的每个元素(索引值)映射到values向量的对应元素,排序逻辑自动基于映射后的值执行,等价于原IndexedValuesComparator的功能,但代码更简洁安全。

基础实现:对现有索引数组排序

假设我们有基础数据结构:

#include <vector>
#include <ranges>
#include <algorithm>

std::vector<int> values = {5, 2, 8, 1, 9};
std::vector<size_t> indexes = {0, 1, 2, 3, 4}; // 初始索引

直接通过投影实现排序:

// 基于values的值对indexes排序,无需自定义谓词
std::ranges::sort(indexes, std::less<>{}, [&values](size_t idx) { return values[idx]; });

第三个参数即为投影逻辑,明确将索引映射为对应值,排序时自动比较这些值。

动态生成排序后的索引

如果不需要保留原索引数组,直接生成排序后的索引序列:

// 生成0到values.size()-1的索引并排序
auto sorted_indexes = std::views::iota(0uz, values.size())
                      | std::ranges::to<std::vector<size_t>>();
std::ranges::sort(sorted_indexes, std::less<>{}, [&values](size_t idx) { return values[idx]; });

C++23支持更简洁的链式写法:

auto sorted_indexes = std::views::iota(0uz, values.size())
                      | std::ranges::sort(std::less<>{}, [&values](size_t idx) { return values[idx]; })
                      | std::ranges::to<std::vector<size_t>>();

多数组多索引绑定与多层间接引用

1. 多数组绑定排序

若需同时基于多个数组的值排序,投影返回包含多值的tuple即可,排序会遵循tuple的默认比较规则(先比较第一个元素,再比较第二个):

std::vector<int> values1 = {5, 2, 8, 1, 9};
std::vector<std::string> values2 = {"e", "b", "h", "a", "i"};
std::vector<size_t> indexes = {0, 1, 2, 3, 4};

std::ranges::sort(indexes, std::less<>{}, [&](size_t idx) {
    return std::make_tuple(values1[idx], values2[idx]);
});

2. 多层间接引用

针对嵌套索引(如索引指向另一索引数组),仅需在投影中完成多层映射:

std::vector<int> values = {5, 2, 8, 1, 9};
std::vector<size_t> secondary_indexes = {3, 1, 0, 4, 2};
std::vector<size_t> indexes = {0, 1, 2, 3, 4};

std::ranges::sort(indexes, std::less<>{}, [&](size_t idx) {
    return values[secondary_indexes[idx]]; // 两层索引映射
});

预留复杂自定义比较逻辑的位置

后续若需复杂比较逻辑,直接替换std::less<>为自定义比较函子即可,投影部分保持独立,完全不影响映射逻辑:

// 自定义比较:先按值的绝对值,再按原值
struct CustomComparator {
    bool operator()(int a, int b) const {
        if (std::abs(a) != std::abs(b)) {
            return std::abs(a) < std::abs(b);
        }
        return a < b;
    }
};

std::ranges::sort(indexes, CustomComparator{}, [&values](size_t idx) { return values[idx]; });

这种方式既移除了老式的IndexedValuesComparator谓词,又能灵活扩展比较逻辑,同时清晰表达索引到值的映射关系,避免了谓词中可能出现的错误。

内容的提问来源于stack exchange,提问作者Damir Tenishev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:57:31