使用STL来填充向量来自地图的键

发布于 2024-12-08 06:01:00 字数 259 浏览 0 评论 0原文

map<T,Z> m= ...;
vector<T> v;
v.reserve(m.size);
for(map<T,Z>::iterator it=m.begin();it!=m.end();++it)
{
 v.push_back(it->first);
}

是否有使用某些 STL 函数的更好的 1 行版本?

编辑:使用c++11!

map<T,Z> m= ...;
vector<T> v;
v.reserve(m.size);
for(map<T,Z>::iterator it=m.begin();it!=m.end();++it)
{
 v.push_back(it->first);
}

Is there a nicer 1-line version using some STL function(s)?

edit: not using c++11!

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

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

发布评论

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

评论(4

尝蛊 2024-12-15 06:01:00

可移植:

struct SelectKey {
  template <typename F, typename S>
  F operator()(const std::pair<const F, S> &x) const { return x.first; }
};

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey());

我认为 STL 的某些实现有一个名为 select1st 的非标准扩展,它相当于此处显示的 SelectKey。正如 K-Ballo 在评论中指出的那样,还有 TR1 版本。我喜欢明确命名的版本,因为它更容易看到发生了什么。

由于不需要状态,因此您可以通过使用实际函数而不是函子来稍微减少样板代码:

template <typename F, typename S>
F SelectKey()(const std::pair<const F, S> &x) { return x.first; }

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey);

如果您可以使用C++11,则可以使用 lambda,它可以保留选择代码靠近它的使用位置:

std::transform(m.cbegin(), m.cend(), std::back_inserter(v),
               [](const std::pair<const F, S> &x) { return x.first; });

甚至是基于范围的 for 循环,这可能是最优雅和可读的:

for(const auto &x : m) {
  v.push_back(x.first);
}

Portable:

struct SelectKey {
  template <typename F, typename S>
  F operator()(const std::pair<const F, S> &x) const { return x.first; }
};

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey());

I think some implementations of STL have a non-standard extension called select1st, which is the equivalent of SelectKey shown here. As K-Ballo pointed out in the comments, there's also a TR1 version. I like the explicitly-named version as it's easier to see what's going on.

Since there's no need for state, you can get away with slightly less boilerplate by using an actual function rather than a functor:

template <typename F, typename S>
F SelectKey()(const std::pair<const F, S> &x) { return x.first; }

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey);

If you could use C++11, you could use a lambda, which keeps the selection code close to where it's used:

std::transform(m.cbegin(), m.cend(), std::back_inserter(v),
               [](const std::pair<const F, S> &x) { return x.first; });

or even range-based for-loop, which is probably the most elegant and readable:

for(const auto &x : m) {
  v.push_back(x.first);
}
假情假意假温柔 2024-12-15 06:01:00

在 C++11 之前,您可以使用转换和自定义函数结构:

template <class K, class V>
struct key_selector : std::unary_function<const std::pair<K, V>&, const K&>
{
    const K& operator()(const std::pair<K, V>& element) const
    {
        return element.first;
    }
};

transform(m.begin(), m.end(), back_inserter(v), key_selector<T,Z>());

如果您有权访问 boost 或 TR1,则可以将 key_selector 替换为 mem_fn

transform(m.begin(), m.end(), back_inserter(v), mem_fn(&map<T,Z>::value_type::first));

在 C++ 之后11、可以使用lambda:

transform(m.begin(), m.end(), back_inserter(v), [](const map<T,Z>::value_type& x) {return x.first;});

Pre C++11, you could use transform and a custom function struct:

template <class K, class V>
struct key_selector : std::unary_function<const std::pair<K, V>&, const K&>
{
    const K& operator()(const std::pair<K, V>& element) const
    {
        return element.first;
    }
};

transform(m.begin(), m.end(), back_inserter(v), key_selector<T,Z>());

If you have access to boost or TR1, you can replace key_selector with mem_fn

transform(m.begin(), m.end(), back_inserter(v), mem_fn(&map<T,Z>::value_type::first));

Post- C++11, you can use lambdas:

transform(m.begin(), m.end(), back_inserter(v), [](const map<T,Z>::value_type& x) {return x.first;});
那片花海 2024-12-15 06:01:00

在 C++11 中,您可以使用 lambda 表达式:

typedef std::map< std::string, std::string > map_t;
map_t map;
std::vector< std::string > v;

std::for_each(map.begin(), map.end(), [&v](map_t::value_type const& it)
        {
            v.push_back(it.first);
        });

In C++11, you can use lambda expressions:

typedef std::map< std::string, std::string > map_t;
map_t map;
std::vector< std::string > v;

std::for_each(map.begin(), map.end(), [&v](map_t::value_type const& it)
        {
            v.push_back(it.first);
        });
过气美图社 2024-12-15 06:01:00

您可以执行以下操作:

std::transform(m.begin(), m.end(), std::back_inserter(v), FUNCTOR);

其中 FUNCTOR 取决于您拥有的 STL 或库和编译器的版本。

C++11 (lambda)

std::transform(m.begin(), m.end(), std::back_inserter(v), [](map<T,Z>::const_reference a) { return a.first; });

C++11 (std::get)

std::transform(m.begin(), m.end(), std::back_inserter(v), &std::get<0>);

C++ SGI STL 有一个名为 select1st 的函子,可以

std::transform(m.begin(), m.end(), std::back_inserter(v), select1st);

像其他人描述的那样使用函子对象来使用 C++03(不是 C++11)。

You can do something along the lines of:

std::transform(m.begin(), m.end(), std::back_inserter(v), FUNCTOR);

Where FUNCTOR depends on what version of the STL or libraries and compilers that you have.

C++11 (lambda)

std::transform(m.begin(), m.end(), std::back_inserter(v), [](map<T,Z>::const_reference a) { return a.first; });

C++11 (std::get)

std::transform(m.begin(), m.end(), std::back_inserter(v), &std::get<0>);

C++ SGI STL has a functor called select1st which can be used

std::transform(m.begin(), m.end(), std::back_inserter(v), select1st);

C++03 (Not C++11) using a functor object like other people have described.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文