【问题标题】:Accessing a partitioned vector within a map访问映射中的分区向量
【发布时间】:2019-02-07 19:55:09
【问题描述】:

我有一个具有以下结构的输入文件

#Latitude   Longitude   Depth [m]   Bathy depth [m] CaCO3 [%] ...
-78 -177    0   693 1
-78 -173    0   573 2
.
.

我创建了一个地图,它有一个基于 string海洋盆地的名称)的键和一个包含数据向量的值。现在我需要按bathyDepth 对向量进行排序。准确地说,我想对向量进行分区,以便我可以在所有数据行之间进行分区,其深度在0500m500m1500m1000m2000m 之间。 ..

我已将数据存储到 map 结构中,但我不确定如何存储和访问分区,以便随后可以cout 特定深度的数据点。

我的尝试:

//Define each basin spatially
//North Atlantic
double NAtlat1 = 0,  NAtlong1 = -70, NAtlat2 = 75, NAtlong2 = -15;
//South Atlantic and the rest...
double SPLIT = 0;

struct Point
{
   //structure Sample code/label--Lat--Long--SedimentDepth[m]--BathymetricDepth[m]--CaCO3[%]--CO3freefraction (SiO2 carb free)[%]--biogenic silica (bSiO2)[%]--Quartz[%]--CO3 ion[umol/l]--CO3critical[umol/l]--Delta CO3 ion[umol/kg]--Ref/source
   string dummy;
   double latitude, longitude, rockDepth, bathyDepth, CaCO3, fCaCO3, bSilica, Quartz, CO3i, CO3c, DCO3;
   string dummy2;
   //Use Overload>> operator
   friend istream& operator>>(istream& inputFile, Point& p);
};

//MAIN FUNCTION
std::map<std::string, std::vector<Point> > seamap;
seamap.insert( std::pair<std::string, std::vector<Point> > ("Nat", vector<Point>{}) );
seamap.insert( std::pair<std::string, std::vector<Point> > ("Sat", vector<Point>{}) );
//Repeat insert() for all other basins

Point p;
while (inputFile >> p && !inputFile.eof() )
{
    //Check if Southern Ocean
    if (p.latitude > Slat2)
    {
        //Check if Atlantic, Pacific, Indian...
        if (p.longitude >= NAtlong1 && p.longitude < SAtlong2 && p.latitude > SPLIT)
        {
            seamap["Nat"].push_back(p);
        } // Repeat for different basins
    }
    else
    {
        seamap["South"].push_back(p);
    }
}
//Partition basins by depth
for ( std::map<std::string, std::vector<Point> >::iterator it2 = seamap.begin(); it2 != seamap.end(); it2++ )
{
    for (int i = 500; i<=4500; i+=500 )
    {
        auto itp = std::partition( it2->second.begin(), it2->second.end(), [&i](const auto &a) {return a.bathyDepth < i;} );
    }
}

注意: a 的类型为 Point。如果我尝试将itp 存储到向量等结构中,则会收到以下错误:

error: no matching function for call to ‘std::vector<Point>::push_back(__gnu_cxx::__normal_iterator<Point*, std::vector<Point> >&)’

我只是不确定如何存储itp。最终目标是计算一个数据点与特定深度窗口内的所有其他数据点之间的距离(例如1500m2500m)。对此新手的任何帮助将不胜感激。

【问题讨论】:

  • 我很确定您可以进一步缩小代码范围,向我们展示您的问题的minimal reproducible example
  • 抱歉,“简单排序”是什么意思?

标签: c++ c++11 stdvector stdmap partition


【解决方案1】:

首先,让我们做一个简单的案例来说明你的问题:

struct Point { int bathyDepth; }; // this is all, what you need to show    

int main()
{
    // some points
    Point a{ 1 }, b{ 100 }, c{ 1000 }, d{ 2000 }, e{ 3000 }, f{ 4000 }, g{ 4501 }, h{ 400 }, i{ 1600 }, j{ 2200 }, k{ 700 };
    // one map element
    std::map<std::string, std::vector<Point> > seamap
    { {"Nat", std::vector<Point>{a, b, c, d, e, f, g, h, i, j, k}} };

    //Partition basins by depth
    for (auto it2= seamap.begin(); it2!= seamap.end(); ++it2)
    {
        int i = 500; // some range
        auto itp = std::partition(it2->second.begin(), it2->second.end(), [&i](const auto &a) {return a.bathyDepth < i; });    
    }

    return 0;
}

我只是不确定如何存储itp

要存储,您只需要知道它的类型。 等于decltype(it2-&gt;second)::iterator,因为std::partition返回容器的迭代器类型。

既然你的地图的key_typestd::vector&lt;Point&gt;,它就等于std::vector&lt;Point&gt;::iterator

您可以通过编程方式对其进行测试:

if (std::is_same<decltype(it2->second)::iterator, decltype(itp)>::value)
   std::cout << "Same type";

这意味着您可以将itp 存储在

using itpType = std::vector<Point>::iterator;
std::vector<itpType> itpVec;
// or any other containers, with itpType

最终目标是计算数据点与所有数据点之间的距离 特定深度窗口内的其他数据点(例如 1500 到 2500m)。

如果是这样,您只需根据bathyDepth 对地图的值(std::vector&lt;Point&gt;)进行排序并遍历它以找到所需的范围。当你使用std::partition 时,在这个循环中

for (int i = 500; i<=4500; i+=500 )

最终效果/结果与一次排序相同,但您需要逐步进行。另外请注意,要使用std::partition 获得正确的结果,您需要一个已排序的std::vector&lt;Point&gt;

例如,查看 example code here,它将打印您提到的范围。

#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>

struct Point
{
    int bathyDepth;
    // provide a operator< for std::sort()
    bool operator<(const Point &rhs)const { return this->bathyDepth < rhs.bathyDepth; }
};
// overloaded  << operator for printing #bathyDepth
std::ostream& operator<<(std::ostream &out, const Point &point) { return out << point.bathyDepth; }

//function for printing/ acceing the range
void printRange(const std::vector<Point>& vec, const int rangeStart, const int rangeEnd)
{
    for (const Point& element : vec)
    {
        if (rangeStart <= element.bathyDepth && element.bathyDepth < rangeEnd) std::cout << element << " ";
        else if (element.bathyDepth > rangeEnd) break; // no need for further checking
    }
    std::cout << "\n";
}

int main()
{
    Point a{ 1 }, b{ 100 }, c{ 1000 }, d{ 2000 }, e{ 3000 }, f{ 4000 }, g{ 4501 }, h{ 400 }, i{ 1600 }, j{ 2200 }, k{ 700 };
    std::map<std::string, std::vector<Point> > seamap
    { {"Nat", std::vector<Point>{a, b, c, d, e, f, g, h, i, j, k}} };

    for (auto it2 = seamap.begin(); it2 != seamap.end(); ++it2)
    {
        // sort it
        std::sort(it2->second.begin(), it2->second.end());
        //Partition basins by depth
        for (int i = 0; i < 4500; i += 500)  printRange(it2->second, i, i + 500);
    }
    return 0;
}

输出:

1 100 400 
700 
1000 
1600 
2000 2200 
                      // no elements in this range
3000 
                      // no elements in this range
4000

【讨论】:

  • 一些问题/要点:(1)-itpVec被使用了吗? (2)-您能解释一下operator&lt;,以及它是如何使用的吗? (3)-假设重载运算符operator&lt;&lt;“直接”打印出一个bathyDepth,而不是输入element.bathyDepth,这是错误的吗?
  • (1) 没有..(对不起,忘记删除了) (2) 见Relational operators here 也读this qestion。 (3) 这就是operator&lt;&lt; 所做的(只是一个合成糖)
【解决方案2】:

std::partition 在分区元素组之间的分离点返回一个迭代器,这是第二组的第一个元素。如果要将其存储在另一个vector 中,则向量类型应为

std::vector<std::vector<Point>::iterator>

您使用它的方式,在随后的分区调用中,您不想对整个向量进行分区,只是对较大元素的部分进行分区(因为向量中的早期元素现在是较低的元素,您不需要将它们包含在以后的分区调用中,因为它们应该在它们所在的位置,并且partition 描述中没有任何内容表明它们不会被移动)。因此,i 循环的后续迭代中的第一个元素应该是前一个循环中返回的 itp 迭代器。

【讨论】:

  • 你介意给我几行代码吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-18
  • 2011-07-05
  • 1970-01-01
  • 2021-12-19
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多