将向量映射到特定范围

Posted

技术标签:

【中文标题】将向量映射到特定范围【英文标题】:Mapping a vector to specific range 【发布时间】:2018-12-23 19:59:19 【问题描述】:

我有一个标准向量,例如包含以下元素

[-6, -7, 1, 2]

我需要将这些元素映射到 1 到 4 的范围内。即我需要向量是这样的

[2, 1, 3, 4]

请注意:第一个向量 (-7) 中的最小值映射到第二个向量 (1) 中的最小值。如何使用 STL 实现这一目标?

【问题讨论】:

获取范围很容易(1my_vector.size())。至于定位,可以通过将第二个向量中的值从小到大排列,然后使用第一个向量中的值进行排序来解决。 @Someprogrammerdude 是的,创建一个范围并对其进行排序是一种选择(参见例如***.com/a/37369858/3182664)。其实这里的具体情况基本上可以认为是寻找一个排序排列(或者它的逆)。 【参考方案1】:

与range-v3:

std::vector<int> v-6, -7, 1, 2;
auto res = ranges::view::ints(1, 1 + (int)v.size()) | ranges::to_vector;

ranges::sort(ranges::view::zip(v, res));

Demo

【讨论】:

谢谢,但我需要一个标准的解决方案,但我会记得使用这个很棒的库。【参考方案2】:

仅使用 C++17(或者实际上是 C++11)中存在的标准库,您可以创建一个索引向量并对其进行排序 - 将其自身用作投影:

vector<int> idxs(values.size());
iota(idxs.begin(), idxs.end(), 1);
sort(idxs.begin(), idxs.end(), [&](int i, int j)
    return values[i-1] < values[j-1];
);

另一种生成索引的方法是使用generate_n

vector<int> idxs;
generate_n(back_inserter(idxs),
    values.size(),
    [cnt=1]() mutable  return cnt++; );
// same sort()

【讨论】:

【参考方案3】:

使用对的辅助向量:

std::vector<int> a  -6, -7, 1, 2 ;

std::vector<std::pair<int, int>> tmp;
for (int i = 0; i < (int) a.size(); ++i) 
    tmp.push_back( a[i], i );


std::sort(tmp.begin(), tmp.end());

std::vector<int> b;
for (auto & x : tmp) 
    b.push_back(x.second + 1);

Demo


使用对的辅助priority_queue(避免显式排序):

std::vector<int> a  -6, -7, 1, 2 ;

std::priority_queue<std::pair<int, int>> tmp;
for (std::size_t i = 0; i < a.size(); ++i) 
    tmp.push( -a[i], i);


std::vector<int> b;
do 
    b.push_back(tmp.top().second + 1);
 while (tmp.pop(), !tmp.empty());

Demo

【讨论】:

以上是关于将向量映射到特定范围的主要内容,如果未能解决你的问题,请参考以下文章

使用整数获取映射到数字范围的值,以在Rust中查找键

本地化:如何将文化信息映射到脚本名称或 Unicode 字符范围?

unordered_map 在使用 [] 运算符时报告“向量下标超出范围”断言

映射范围内的特定办公室

如何编写使用临时容器的范围管道?

是否有将范围移动到向量中的标准方法?