C++ std::transform 成对向量 -> 第一个到新向量

发布于 2025-01-01 03:25:54 字数 775 浏览 6 评论 0原文

抱歉,有一点初学者问题。有向量和对向量

typedef std::vector <int> TItems;
typedef std::vector < std::pair <int, int> > TPairs;

有没有办法一步将所有第一个项目对转换为另一个向量

int main ()
{
TItems items;
TPairs pairs;

pairs.push_back (std::make_pair(1,3));
pairs.push_back (std::make_pair(5,7));

std::transform( items.begin(), items.end(), items.begin(), comp ( &pairs ) );

return 0;
}

如何设计函子?

class comp
{
private:
     TPairs *pairs;

public:
    comp ( TPairs  *pairs_ ) : pairs ( pairs_) { }

    unsigned int operator () ( const unsigned int index ) const
    {
        return  (*pairs)[index].second != pairs->end();  //Bad idea
    }
};

也许有一些更用户友好的方法,无需 lambda 表达式和循环。感谢您的帮助。

Sorry for a little bit beginner question. There are vector and vector of pairs

typedef std::vector <int> TItems;
typedef std::vector < std::pair <int, int> > TPairs;

Is there any way to transform all first items in pair to another vector in one step

int main ()
{
TItems items;
TPairs pairs;

pairs.push_back (std::make_pair(1,3));
pairs.push_back (std::make_pair(5,7));

std::transform( items.begin(), items.end(), items.begin(), comp ( &pairs ) );

return 0;
}

How to design a functor?

class comp
{
private:
     TPairs *pairs;

public:
    comp ( TPairs  *pairs_ ) : pairs ( pairs_) { }

    unsigned int operator () ( const unsigned int index ) const
    {
        return  (*pairs)[index].second != pairs->end();  //Bad idea
    }
};

Maybe there is some more user friendly method without lambda expressions and loops. Thanks for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

月亮邮递员 2025-01-08 03:25:54

首先,您应该使用 back_inserter作为 transform 的第三个参数,以便转换后的值被推到向量的后面。

其次,您需要某种函子,它接受一对整数并返回第一个整数。应该这样做:

int firstElement( const std::pair<int, int> &p ) {
    return p.first;
}

现在,将各个部分放在一起:

TPairs pairs;
pairs.push_back( std::make_pair( 1, 3 ) );
pairs.push_back( std::make_pair( 5, 7 ) );

TItems items;
std::transform( pairs.begin(), pairs.end(), std::back_inserter( items ),
                firstElement );

在此代码之后,items 包含 1 和 5。

First of all, you should use a back_inserter as the third argument to transform so that the transformed values are pushed to the back of the vector.

Second, you need some sort of functor which takes a pair of ints and returns the first one. This should do:

int firstElement( const std::pair<int, int> &p ) {
    return p.first;
}

Now, to put the pieces together:

TPairs pairs;
pairs.push_back( std::make_pair( 1, 3 ) );
pairs.push_back( std::make_pair( 5, 7 ) );

TItems items;
std::transform( pairs.begin(), pairs.end(), std::back_inserter( items ),
                firstElement );

After this code, items contains 1 and 5.

笔落惊风雨 2025-01-08 03:25:54

请参阅 frerich 或 kotlinski 对 C++03 的回答。

使用 lambda 的 C++11 解决方案:

std::transform(pairs.begin(), 
               pairs.end(), 
               std::back_inserter(items), 
               [](const std::pair<int, int>& p) { return p.first; });

see frerich's or kotlinski's answer for C++03.

C++11 solution with lambda:

std::transform(pairs.begin(), 
               pairs.end(), 
               std::back_inserter(items), 
               [](const std::pair<int, int>& p) { return p.first; });
风透绣罗衣 2025-01-08 03:25:54

我真的希望您使用 std::get 作为函子,因为它已经作为库函数提供了!

如果我们能写出这一行岂不是很好!?

std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);

……但比这更可怕一点。您需要消除要使用的 get 的歧义:

int main() {
  std::vector<int> items;
  std::vector<std::pair<int, int>> pairs;

  pairs.push_back(std::make_pair(1, 3));
  pairs.push_back(std::make_pair(5, 7));

  std::transform(pairs.begin(), pairs.end(), std::back_inserter(items),
                 (const int& (*)(const std::pair<int, int>&))std::get<0>);

  return 0;
}

问题是 std::get 重载以获取 1. pair&、2. constpair& 和 3. pair&& 作为参数,以便它适用于任何类型的对作为输入。不幸的是,重载妨碍了 std::transform 的模板类型推导,因此我们的原始行

std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);

产生

 error: no matching function for call to ‘transform(std::vector<std::pair<int, int> >::iterator, std::vector<std::pair<int, int> >::iterator, std::back_insert_iterator<std::vector<int> >, <unresolved overloaded function type>)’
   std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);
                                                                                    ^
...

/usr/include/c++/4.8/bits/stl_algo.h:4915:5: note:   template argument deduction/substitution failed:
 note:   couldn't deduce template parameter ‘_UnaryOperation’
   std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);

It 不知道 std::get 的哪个重载您在推导 std::transform 模板时要求,因此您必须手动指定它。将函数指针转换为正确的类型告诉编译器,“嘿,请使用重载,其中 get 接受 const& 并返回 const& >!”

但至少我们正在使用标准库组件(是的)?

就行数而言,它并不比其他选项差:
http://ideone.com/6dfzxz

I really want you to use std::get as the functor, because it's already provided as a library function!!

Wouldn't it be great if we could write this line!?

std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);

... But it's a bit more terrible than that. You need to disambiguate which get to use:

int main() {
  std::vector<int> items;
  std::vector<std::pair<int, int>> pairs;

  pairs.push_back(std::make_pair(1, 3));
  pairs.push_back(std::make_pair(5, 7));

  std::transform(pairs.begin(), pairs.end(), std::back_inserter(items),
                 (const int& (*)(const std::pair<int, int>&))std::get<0>);

  return 0;
}

The problem is, std::get is overloaded to take 1. pair&, 2. const pair&, and 3. pair&& as the parameters, so that it will work for any sort of pair as input. Unfortunately, the overloads get in the way of the template type deduction for std::transform, so our original line

std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);

yields

 error: no matching function for call to ‘transform(std::vector<std::pair<int, int> >::iterator, std::vector<std::pair<int, int> >::iterator, std::back_insert_iterator<std::vector<int> >, <unresolved overloaded function type>)’
   std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);
                                                                                    ^
...

/usr/include/c++/4.8/bits/stl_algo.h:4915:5: note:   template argument deduction/substitution failed:
 note:   couldn't deduce template parameter ‘_UnaryOperation’
   std::transform(pairs.begin(), pairs.end(), std::back_inserter(items), std::get<0>);

It doesn't know which overload of std::get you are asking for when deducing the template for std::transform, so you have to specify it manually. Casting the function pointer to the right type tells the compiler, "Hey, please use the overload where get takes a const& and returns a const&!"

But at least we're using standard library components (yay)?

And in terms of number of lines, it's no worse than the other options:
http://ideone.com/6dfzxz

故事与诗 2025-01-08 03:25:54

这个怎么样?

items.reserve(pairs.size());
for (size_t it = 0; it < pairs.size(); ++it) {
    items.push_back(pairs[it].first);
}

易于理解和调试。

How about this?

items.reserve(pairs.size());
for (size_t it = 0; it < pairs.size(); ++it) {
    items.push_back(pairs[it].first);
}

Simple to understand and debug.

使用 std::bind 怎么样?

std::transform(pairs.begin(), 
               pairs.end(), 
               std::back_inserter(items), 
               std::bind(&TPairs::value_type::first, std::placeholders::_1));

(对于非 C++11 代码,将 std::bind 替换为 boost::bind

How about using std::bind?

std::transform(pairs.begin(), 
               pairs.end(), 
               std::back_inserter(items), 
               std::bind(&TPairs::value_type::first, std::placeholders::_1));

(Replace std::bind by boost::bind for non-C++11 code)

泪之魂 2025-01-08 03:25:54

C++11 的另一种可能性是 std::mem_fn,与 std::bind 的解决方案类似:

std::transform(pairs.begin(), 
               pairs.end(), 
               std::back_inserter(items), 
               std::mem_fn(&std::pair<int,int>::first)               
);

another possibility from C++11 would be std::mem_fn, which is similar to solution with std::bind:

std::transform(pairs.begin(), 
               pairs.end(), 
               std::back_inserter(items), 
               std::mem_fn(&std::pair<int,int>::first)               
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文