为成对容器的第一个元素提供迭代器

时间:2021-10-09 21:58:51

I have a container filled with pairs. I want to iterate in it using the STL generic algorithms (in my case it would be inner_product, but consider it as a generic problem). The algorithm I am using expects iterators first and last. Can I provide special iterators first and last that will iterate not on the pairs but on the first element of each pair?

我有一个装满对的容器。我想使用STL泛型算法迭代它(在我的情况下,它将是inner_product,但将其视为一般问题)。我正在使用的算法首先要求使用迭代器。我可以首先提供特殊的迭代器,并且不会在对上迭代但是在每对的第一个元素上迭代吗?

I know i can do it manually, providing a hand-made function object that will be a wrapper around the standard container iterator, deferencing it to the first member of the pair intend of the pair itself,but I think there is also a clever one-liner to do it for me. What would it be?

我知道我可以手动完成,提供一个手工制作的函数对象,它将成为标准容器迭代器的包装器,将它引用到该对本身的第一个成员中,但我认为还有一个聪明的-liner为我做这件事。会是什么?

4 个解决方案

#1


11  

I've looked around and found boost::transform_iterator. I've come up with this code. Surprising how well it works:

我环顾四周,发现了boost :: transform_iterator。我想出了这段代码。令人惊讶的是它的工作原理:

#include <map>
#include <algorithm>
#include <iostream>
#include <string>
#include <iterator>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>

int main() {
    typedef std::map<std::string, int>::value_type value_type;
    std::map<std::string, int> a;
    a["one"] = 1;
    a["two"] = 2;

    // returns the second element 
    boost::function<int(value_type&)> f = boost::bind(&value_type::second, _1);
    std::copy(boost::make_transform_iterator(a.begin(), f), 
              boost::make_transform_iterator(a.end(), f),
              std::ostream_iterator<int>(std::cout, " "));

}

It's printing "1 2 " to the standard output.

它在标准输出上打印“1 2”。

#2


1  

There is no clever one-liner solution. Your best hope is to write a wrapper iterator. This is actually a pretty canonical solution. You might check whether Boost already has what you need. If not, try to write a generic wrapper that can be reused for other problems.

没有聪明的单线解决方案。你最好的希望是编写一个包装器迭代器。这实际上是一个非常规范的解决方案。您可以检查Boost是否已满足您的需求。如果没有,请尝试编写一个可以重用于其他问题的通用包装器。

The STL contains such an iterator wrapper called reverse_iterator. The name implies its use.

STL包含一个名为reverse_iterator的迭代器包装器。这个名字意味着它的使用。

#3


1  

Ultimately, I think your idea is the way to go. You can use Boost to help you do it. To start, you'd need a function that takes your pair and returns the first element. I think you could write such a function in-line using the Lambda library, but for readability's sake, I think I'd just write a simple function that does that instead. Then pass that function with your original iterators to construct a transform_iterator for your sequence's begin and end.

最终,我认为你的想法是要走的路。您可以使用Boost来帮助您。首先,你需要一个带你的对的函数并返回第一个元素。我想你可以使用Lambda库在线编写这样的函数,但为了便于阅读,我想我只是编写了一个简单的函数来代替它。然后使用原始迭代器传递该函数,为序列的开始和结束构造transform_iterator。

#4


1  

You can subclass e.g. std::vector::const_iterator yourself, reimplementing operator* and operator-> to return the first of the pair. You'd also need to create your own begin() and end() functions to return your custom iterator.

你可以子类化,例如std :: vector :: const_iterator你自己,重新实现operator *和operator->来返回第一个对。您还需要创建自己的begin()和end()函数以返回自定义迭代器。

You can also create to binary function classes and pass those to inner_product.

您还可以创建二进制函数类并将它们传递给inner_product。

#1


11  

I've looked around and found boost::transform_iterator. I've come up with this code. Surprising how well it works:

我环顾四周,发现了boost :: transform_iterator。我想出了这段代码。令人惊讶的是它的工作原理:

#include <map>
#include <algorithm>
#include <iostream>
#include <string>
#include <iterator>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>

int main() {
    typedef std::map<std::string, int>::value_type value_type;
    std::map<std::string, int> a;
    a["one"] = 1;
    a["two"] = 2;

    // returns the second element 
    boost::function<int(value_type&)> f = boost::bind(&value_type::second, _1);
    std::copy(boost::make_transform_iterator(a.begin(), f), 
              boost::make_transform_iterator(a.end(), f),
              std::ostream_iterator<int>(std::cout, " "));

}

It's printing "1 2 " to the standard output.

它在标准输出上打印“1 2”。

#2


1  

There is no clever one-liner solution. Your best hope is to write a wrapper iterator. This is actually a pretty canonical solution. You might check whether Boost already has what you need. If not, try to write a generic wrapper that can be reused for other problems.

没有聪明的单线解决方案。你最好的希望是编写一个包装器迭代器。这实际上是一个非常规范的解决方案。您可以检查Boost是否已满足您的需求。如果没有,请尝试编写一个可以重用于其他问题的通用包装器。

The STL contains such an iterator wrapper called reverse_iterator. The name implies its use.

STL包含一个名为reverse_iterator的迭代器包装器。这个名字意味着它的使用。

#3


1  

Ultimately, I think your idea is the way to go. You can use Boost to help you do it. To start, you'd need a function that takes your pair and returns the first element. I think you could write such a function in-line using the Lambda library, but for readability's sake, I think I'd just write a simple function that does that instead. Then pass that function with your original iterators to construct a transform_iterator for your sequence's begin and end.

最终,我认为你的想法是要走的路。您可以使用Boost来帮助您。首先,你需要一个带你的对的函数并返回第一个元素。我想你可以使用Lambda库在线编写这样的函数,但为了便于阅读,我想我只是编写了一个简单的函数来代替它。然后使用原始迭代器传递该函数,为序列的开始和结束构造transform_iterator。

#4


1  

You can subclass e.g. std::vector::const_iterator yourself, reimplementing operator* and operator-> to return the first of the pair. You'd also need to create your own begin() and end() functions to return your custom iterator.

你可以子类化,例如std :: vector :: const_iterator你自己,重新实现operator *和operator->来返回第一个对。您还需要创建自己的begin()和end()函数以返回自定义迭代器。

You can also create to binary function classes and pass those to inner_product.

您还可以创建二进制函数类并将它们传递给inner_product。