vector / C ++ / STL的子集

时间:2015-03-19 19:08:56

标签: c++ vector struct stl subset

我想提取一个填充了结构的向量的子集,并形成一个新的向量,该向量只填充该子集的一个成员变量。

主矢量用这样的结构填充:

struct ImageParams{
    double startTime;
    double stopTime;
    std::string path;
    std::string activeInstrument;
    bool projected;
}; 

所以说我的申请已经从t0跳过了 - > t1,然后我想要在t0和t之间的每个startTime。 T1。我目前使用二进制查找操作遍历主向量,并将每个startTime存储在一个新的返回向量中,如下所示:

captureTime = t1;   
while (captureTime > t0){
        auto binary_find = [](std::vector<ImageParams>::iterator begin,
            std::vector<ImageParams>::iterator end,
            const ImageParams &val,
            bool(*cmp)(const ImageParams &a, const ImageParams &b))->std::vector<ImageParams>::iterator{
            std::vector<ImageParams>::iterator it = std::lower_bound(begin, end, val, cmp);
            if (it != begin){
                return std::prev(it);
            }
            return end;
        };
        // Finds the lower bound in at most log(last - first) + 1 comparisons
        auto it = binary_find(mainVec.begin(), mainVec.end(), 
                             { captureTime, 0, "", "", false }, cmp);

        if (it == mainVec.end()) return false;
        if (it->startTime < t0) break;

        returnVec.push_back(it->startTime);

        captureTime = it->startTime - 1;
    }

我想要实现的目标: 这有效,但我认为它与while循环看起来很难看。我想也许有一种有效的方法(如果在mainVec中找到一个匹配时间t0和t1的两个iter-position),就形成一个只有startTime成员变量的新向量。

我想象这样的事情,

std::vector<double> returnVec = std::vector(mainVec.begin () + first,
                                            mainVec.begin () + last);

但可以说“只提取startTime成员变量”

也许我会过度思考它?

2 个答案:

答案 0 :(得分:2)

以下是使用std::transform的示例:

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

struct ImageParams {
    double startTime;
    double stopTime;
    std::string path;
    std::string activeInstrument;
    bool projected;
};

int main()
{
    // Our initial vector of ImageParams
    const std::vector<ImageParams> vec {
        { 1.0, 0.0, std::string(), std::string(), false },
        { 2.0, 0.0, std::string(), std::string(), false },
        { 3.0, 0.0, std::string(), std::string(), false },
        { 4.0, 0.0, std::string(), std::string(), false }
    };

    // A subset of our initial vector's startTimes
    std::vector<double> subset;
    std::transform(vec.begin() + 1, vec.end(),
                   std::back_inserter(subset),
                   [](const ImageParams& i) { return i.startTime; });

    // Print the subset
    std::cout << "subset contains: ";
    for (double d : subset) {
        std::cout << d << ' ';
    }

    return 0;
}

输出:

subset contains: 2 3 4 

在最简单的形式中,std::transform接受一系列元素(通过第一个和最后一个迭代器),一个目标迭代器(这里我们使用std::back_inserter将转换函数的结果插入到子集向量中),我们传递一个lambda函数来提取每个ImageParams元素的开始时间。

答案 1 :(得分:1)

(完全重复我的回答以回复评论 - 你可以在编辑历史中看到原文。)

如果您使用的是C ++ 11,则可以使用std::transform和仿函数或lambda执行此操作:

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

struct ImageParams
{
    double startTime;
    double stopTime;
    std::string path;
    std::string activeInstrument;
    bool projected;
};

struct ExtractStartTime
{
    double operator()(const ImageParams& params) const
    {
        return params.startTime;
    }
};

int main()
{
    ImageParams params = { 1.0, 0.0, std::string(), std::string(), false };

    std::vector<ImageParams> big_vec(5, params);
    big_vec[4].startTime = 5.0;

    std::vector<double> small_vec;

    std::transform(big_vec.begin() + 2, big_vec.end(), std::back_inserter(small_vec), ExtractStartTime());

    for(int i = 0; i < small_vec.size(); ++i)
    {
        std::cout << "[" << i << "]: " << small_vec[i] << std::endl;
    }
}