如何通过视图对数据进行索引排序?

问题描述 投票:0回答:1

在下面的代码中,

values
向量包含由
indexes
索引的数据。模板
indexing
允许对像
std::ranges::equal_range
这样的函数进行透明索引,但我没有看到使用范围/投影/视图方法对索引数组(不是值本身!)进行排序的方法。 我能做的是创建一个“旧式”谓词
IndexedValuesComparator
进行排序并将其用于
std::ranges::sort

是否有机会在没有谓词的情况下用视图之美来表达相同的内容?这可以像使用

indexing
模板一样完成吗?

正如我所看到的问题,我需要比较值,但是交换索引,而这不能通过仅提供一个实体的视图来完成。有没有简单直接的解决办法?

动机

我需要将许多数组与许多索引绑定,有时需要多个间接级别,所以我希望有一种简短而安全的方式来表达这一点。

#include <vector>
#include <concepts>
#include <ranges>
#include <algorithm>
#include <iostream>

// Reusable generic for the custom view approach
template<typename Index, std::ranges::random_access_range R>
auto indexing(R&& range) {
    return std::views::transform([&range](const Index& i) -> decltype(auto) {
        return std::ranges::begin(range)[i];
        });
};

template<typename Value> 
class IndexedValuesComparator {
    const std::vector<int>::const_iterator vec;
public: 
    IndexedValuesComparator(const std::vector<int>::const_iterator& vec) : vec(vec) {}

    bool operator() (const auto& lhs, const auto& rhs) {
        return vec[lhs] < vec[rhs];
    }
};

int main()
{
    std::vector<int> values = { 0,30,20,40,10 };
    std::vector<int> indexes = { 3,4,2,1,0 };

    auto indexing_view = indexes | indexing<int>(values);

    std::ranges::sort(indexes, IndexedValuesComparator<int>(values.begin()));

    int value_to_search(30);

    auto range_pred2 = std::ranges::equal_range(indexing_view, value_to_search);
    std::cout << "*range_pred.first = " << *(range_pred2.begin()) << std::endl;
    std::cout << "*range_pred.second= " << *(range_pred2.end()) << std::endl;

    std::cout << std::endl << "range_pred.second-range_pred.first " << std::distance(range_pred2.begin(), range_pred2.end()) << std::endl;
}

演示

c++ stl std-ranges
1个回答
0
投票

您可以使用变量模板 lambda 来创建自定义投影:

template<typename Index>
auto make_index_proj = []<std::ranges::random_access_range R>(R&& range) {
  return [&range](const Index& i) -> decltype(auto) {
    return std::ranges::begin(range)[i];
  };
};

然后将投影统一传递给

views::transform
ranges::sort

std::vector<int> values = { 0,30,20,40,10 };
std::vector<int> indexes = { 3,4,2,1,0 };

auto my_proj = make_index_proj<int>(values);
auto indexing_view = indexes | std::views::transform(my_proj);
std::ranges::sort(indexes, {}, my_proj);
© www.soinside.com 2019 - 2024. All rights reserved.