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

ehxuflar  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(87)

在下面的代码中,values向量包含由indexes索引的数据。模板indexing允许对std::ranges::equal_range这样的函数进行透明索引,但我看不到对索引数组进行排序的方法(不重视自己!我可以做的是创建一个“老式” predicate IndexedValuesComparator用于排序,并将其用于std::ranges::sort
有没有机会在没有 predicate 的情况下用视图之美来表达同样的内容?这可以用与indexing模板相同的方式来完成吗?
当我看到这个问题时,我需要比较值,但是交换索引,这不能用只提供一个实体的视图来完成。有没有一个简单的解决方案?
所以,我只需要IndexedValuesComparator做什么,但没有它和视图风格。
如果视图可以用来动态地获取已排序的索引(而不存储值),那就太好了,但这是可选的。

动机

1.我需要有许多数组与许多索引的绑定,有时与许多间接级别,所以我想有简短和安全的方式来表达这一点。
1.我想去掉比较器,因为我需要这个“地方”来放置其他比较器,这些比较器将执行更复杂的工作,我不想将它们与现有的比较器混合在一起。

#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;
}

字符串
Demo

lskq00tm

lskq00tm1#

您可以先创建一个创建自定义投影的lambda

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

字符串
(Note我们可能需要接受左值范围以避免悬空。此外,random_access_iterator只与它的difference_type一起工作,因此不需要指定索引类型,range_difference_t已经为我们做了这一点)
然后将投影均匀地传递到views::transformranges::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(values);

auto indexing_view = indexes | std::views::transform(my_proj);
std::ranges::sort(indexes, {}, my_proj);

相关问题