【问题标题】:Unroll std::vector<std::vector<T>> to std::vector<T>展开 std::vector<std::vector<T>> 到 std::vector<T>
【发布时间】:2015-04-14 14:17:25
【问题描述】:

我需要在代码的很多地方将std::vector&lt;std::vector&lt;T&gt;&gt; 转换为std::vector&lt;T&gt;(逐行)。我显然知道如何自己实现它,但是在 boost 或 stl 中是否有任何短代码解决方案? (我只能使用 C++98)

UPD:我需要一些非常简短的解决方案,例如某些函数的单行调用(可能使用 boost lambda),没有循环,因此来自C++ pushing elements of a vector of vectors into a vector 的解决方案是不可接受的。

UPD2:请不要用循环发布答案,我知道该怎么做。问题是短代码方式,而不是想法。

【问题讨论】:

标签: c++ boost stl


【解决方案1】:

由于它在很多地方,最好编写自己的小型包装函数将其放在所有这些地方。包装器内部的逻辑可以根据性能进行定制,因为它现在在一个地方。最简单的可能是

inline template <typename T> 
std::vector<T> to_vector(const std::vector<std::vector<T>>& double_vec) {
  std::vector<T> output;
  for(std::vector<std::vector<T>>::size_type i=0; i < double_vec.size(); ++i) {
    output.insert(output.end(), double_vec[i].begin(), double_vec[i].end());
  }
  return output;
}

如有必要,可以自定义/优化。

【讨论】:

  • 正如我所说,我知道如何自己制作。我需要一些解决方案,在没有循环的情况下调用某个函数(例如某个遍历器)。请仔细阅读问题。
  • 我不同意;除了使用 size_t 而不是 vector&lt;T&gt;::size_type 和依赖返回值优化之外,这是一个很好的答案。
  • @brachistochron 好吧,当我回答时,没有关于循环的条件:)。无论哪种方式,您都需要访问原始向量的每个元素一次来复制它,所以无论如何都会有循环 - 遍历一些 boost lambda 只会隐藏循环。提议的解决方案本质上是相同的 - 在调用站点公开短函数,将转换逻辑封装在一个地方:)
  • @Bathsheba,感谢您的评论,我已经更新了 vector::size_type。关于返回值优化 - 我认为使用现代编译器来简化接口是公平的,而不是通过指针返回添加样板代码 - 除非您知道在您使用的情况下没有返回值优化。
【解决方案2】:

没有循环就没有办法做到这一点,事实上,这个任务几乎是使用循环的典型代表。好吧,如果我们是迂腐的话,嵌套循环。

您可以做的是隐藏您正在使用更高级别的构造进行循环的事实,但底层实现将是一组嵌套循环。

template <typename T>
struct flatten_functor
{
   flatten_functor(std::vector<T> &out)
     : m_out(out)
   {}

   bool operator()(std::vector<T> const& to_append)
   {
      m_out.insert(m_out.end(), to_append.begin(), to_append.end());
      return true;
   }
private:
  std::vector<T>& m_out;
};

template <typename T>
std::vector<T> flatten_vector(std::vector<std::vector<T> > const &in)
{
  std::vector<T> retval;
  flatten_functor<T> flatten_this(retval);

  std::for_each(in.begin(), in.end(), flatten_this);

  return retval;
}

如您所见,要真正隐藏您正在处理循环的事实需要付出很多努力。我不认为它比循环更具可读性,但是这些天我大部分时间都在使用 C++11,而且使用 lambdas 更容易清理这段代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-02
    • 2017-09-01
    • 2019-10-20
    • 2016-03-31
    • 2019-11-07
    • 2012-06-21
    • 2011-12-27
    • 2021-06-02
    相关资源
    最近更新 更多