【问题标题】:Subset of vector / C++ / STL向量子集/C++/STL
【发布时间】:2015-03-19 19:08:56
【问题描述】:

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

主向量填充了这样的结构:

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

假设我的应用程序已从 t0 -> t1 跳转,那么我希望每个 startTime 在 t0 和 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 的迭代位置)来形成一个只有 startTime 成员变量的新向量。

我想像这样,

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

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

也许是我想多了?

【问题讨论】:

标签: c++ vector struct stl subset


【解决方案1】:

这里是一个使用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 元素的开始时间。

【讨论】:

    【解决方案2】:

    (完全重做我的回答以回应评论 - 您可以在编辑历史记录中看到原始答案)。

    如果你有 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;
        }
    }
    

    【讨论】:

    • 是否可以不将返回向量声明为 std::vector 类型,而是将其作为 std::vector ?即从 std::vector 获取范围并仅提取每个结构的 startTime 成员并将它们全部直接传递给 std::vector ?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 2016-04-01
    相关资源
    最近更新 更多