简体   繁体   English

c++ get std::vector<int> 来自 std::vector <std::tuple<int, float> &gt;

[英]c++ get std::vector<int> from std::vector<std::tuple<int, float>>

i want to initialize a const std::vector<int> member variable in the initializer list of a constructor, given a std::vector<std::tuple<int, float>> constructor argument.我想在构造函数的初始化列表中初始化一个const std::vector<int>成员变量,给定一个std::vector<std::tuple<int, float>>构造函数参数。 The vector should contain all the first tuple items.该向量应包含所有第一个元组项。

Is there a one-liner that extracts an std::vector<int> containing all the first tuple entries from an std::vector<std::tuple<int, float>> ?是否有一衬垫,其提取一个std::vector<int>包含所有第一元组从条目std::vector<std::tuple<int, float>>

With C++20 ranges:使用 C++20 范围:

struct X
{
    const std::vector<int> v;

    template <std::ranges::range R>
        requires std::convertible_to<std::ranges::range_value_t<R>, int>
    X(R r)
        : v{r.begin(), r.end()}
    {}

    X(const std::vector<std::tuple<int, float>>& vt)
        : X{vt | std::ranges::views::elements<0>}
    {}
};

With ranges-v3:使用范围-v3:

struct X
{
    const std::vector<int> v;

    X(const std::vector<std::tuple<int, float>>& vt)
        : v{vt | ranges::views::transform([] (auto t) {
                    return std::get<0>(t); })
               | ranges::to<std::vector>()}
    {}
};

And a Frankenstein's monster:还有一个科学怪人的怪物:

#include <ranges>
#include <range/v3/range/conversion.hpp>

struct X
{
    const std::vector<int> v;

    X(const std::vector<std::tuple<int, float>>& vt)
        : v{vt | std::ranges::views::elements<0>
               | ranges::to<std::vector>()}
    {}
};

Adding to @bolov's answer, let's talk about what you might have liked to do, but can't in a one-liner.添加到@bolov 的答案中,让我们谈谈您可能喜欢做什么,但不能单行。

  • There's the to<>() function from ranges-v3 from @bolov 's answer - it materializes a range into an actual container (a range is lazily-evaluated, and when you create it you don't actually iterate over the elements). @bolov 的答案中有来自 range-v3 的to<>()函数 - 它将一个范围具体化到一个实际的容器中(一个范围是惰性求值的,当你创建它时,你实际上并没有迭代元素) . There is no reason it shouldn't be in the standard library, if you ask me - maybe they'll add it 2023?如果你问我,它没有理由不应该出现在标准库中——也许他们会在 2023 年添加它?

  • You may be wondering - why do I need that to() ?你可能想知道 - 为什么我需要那个to() Can't I just initialize a vector by a range?我不能按范围初始化一个向量吗? And the answer is - sort of, sometimes, maybe.答案是 - 有点,有时,也许。 Consider this program:考虑这个程序:

     #include <vector> #include <tuple> #include <ranges> void foo() { using pair_type = std::tuple<int, double>; std::vector<pair_type> tvec { {12, 3.4}, {56, 7.8}, { 90, 91.2} }; auto tv = std::ranges::transform_view( tvec, [](const pair_type& p) { return std::get<0>(p);} ); std::vector<std::tuple<int>> vec1 { tv.begin(), tv.end() }; std::vector<std::tuple<int>> vec2 { std::ranges::transform_view{ tvec, [](const pair_type& p) { return std::get<0>(p);} }.begin(), std::ranges::transform_view{ tvec, [](const pair_type& p) { return std::get<0>(p);} }.end() }; }

    The vec1 statement will compile just fine, but the vec2 statement will fail . vec1语句将编译得很好,但vec2语句将失败 This is surprising (to me anyway)!这令人惊讶(无论如何对我来说)!

  • You may also be wondering why you even need to go through ranges at all.您可能还想知道为什么您甚至需要遍历范围。 Why isn't there a...为什么没有...

     template <typename Container, typename UnaryOperation> auto transform(Container&& container, UnaryOperation op);

    which constructs the transformed container as its return value?哪个构造转换后的容器作为其返回值? That would allow you to write:这将允许你写:

     std::vector<std::tuple<int>> vec3 { transform( tvec, [](const pair_type& p) { return std::get<0>(p); } ) }

    ... and have that work. ......并完成这项工作。 Well, we just don't have functions in the standard libraries which take containers.好吧,我们只是在标准库中没有使用容器的函数。 It's either iterator pairs, which is the "classic" pre-C++20 standard library, or ranges.它要么是迭代器对,它是“经典的”C++20 之前的标准库,要么是范围。 But there is nothing preventing you from writing that very function!但是没有什么可以阻止您编写该函数! It's not even that difficult, except perhaps with the care you need for the forwarding reference.这甚至不是那么困难,除非您需要注意转发参考。

Not a one-liner to setup, but certainly one to use - you can write a function to do the conversion, and then the constructor can call that function when initializing the vector member, eg:不是单行设置,但肯定可以使用 - 您可以编写一个函数来进行转换,然后构造函数可以在初始化向量成员时调用该函数,例如:

std::vector<int> convertVec(const std::vector<std::tuple<int, float>> &arg)
{
    std::vector<int> vec;
    vec.reserve(arg.size());
    std::transform(arg.begin(), arg.end(), std::back_inserter(vec),
        [](const std::tuple<int, float> &t){ return std::get<int>(t); }
    );
    return vec;
}

struct Test
{
    const std::vector<int> vec;

    Test(const std::vector<std::tuple<int, float>> &arg)
        : vec(convertVec(arg))
    {
    } 
};

Yes, there is a one-liner if you use this library in Github .是的,如果您在 Github 中使用此库,则有一个单行。

The code goes like this.代码是这样的。

#include <iostream>
#include <tuple>
#include <vector>

#include <LazyExpression/LazyExpression.h>

using std::vector;
using std::tuple;
using std::ref;
using std::cout;

using LazyExpression::Expression;

int main()
{
    // Define test data
    vector<tuple<int, float>> vecTuple { {1,1.1}, {2,2.2}, {3, 3.3} };

    // Initialize int vector with the int part of the tuple (the one-liner :)
    vector<int> vecInt = Expression([](const tuple<int, float>& t) { return std::get<int>(t); }, ref(vecTuple))();

    // print the results
    for (int i : vecInt)
        cout << i << ' ';
    cout << "\n";
}
// Output:  1 2 3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C++:错误无法从 std::vector 转换<int> * 到 std::vector <std::vector<int> &gt; </std::vector<int></int> - C++ : Error could not convert from std::vector<int>* to std::vector<std::vector<int> > 向 std::vector 添加成员<std::vector<int> &gt; class 在 C++ </std::vector<int> - Adding a member to std::vector<std::vector<int>> class in C++ C ++ std :: vector <int> 问题 - C++ std::vector<int> issue 如何返回std :: vector <std::vector<int> &gt;从C ++到C ++ / CLI? - How to return std::vector<std::vector<int>> from C++ to C++/CLI? 如何返回std :: vector <std::pair<std::string, int> &gt;使用Swig类型映射从Java转换为C ++ - How to return std::vector<std::pair<std::string, int> > from java to c++ using swig typemaps 如何使用std :: map检索std :: vector <int> 在C ++中? - How to use std::map to retrive a std::vector<int> in c++? 从std :: vector转换 <int> 转换为char [] C ++ - Converting from a std::vector<int> to a char[] C++ C++ 转换 std::tuple<A, A, A…> 到 std::vector 或 std::deque - C++ Transform a std::tuple<A, A, A…> to a std::vector or std::deque C ++错误:没有匹配的函数可以调用&#39;std :: vector <int> ::交换(标准::矢量 <int> )” - C++ Error: no matching function for call to 'std::vector<int>::swap(std::vector<int>)' 标准::向量<int>到 std::vector<enum></enum></int> - std::vector<int> to std::vector<enum>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM