【问题标题】:Is there a more idiomatic way to split a std::vector?有没有更惯用的方法来拆分 std::vector?
【发布时间】:2015-01-31 07:48:40
【问题描述】:

我编写了一个函数,可以将大小为 N 的向量拆分成大小不超过 M 的块。

所以给定一个大小为 47 的向量,块大小为 10,我们得到 5 个大小的块:10,10,10,10,7。

template<typename T> std::vector<std::vector<T>> chunkVector(typename std::vector<T> source, typename std::vector<T>::size_type chunkSize)
{
    typename std::vector<std::vector<T>> returnVector;

    for (typename std::vector<T>::size_type i = 0; i < source.size(); i += chunkSize) {

        typename std::vector<T>::iterator start = source.begin() + i;
        typename std::vector<T>::iterator end = start + chunkSize > source.end() ? source.end() : start + chunkSize;
        typename std::vector<T> tempVector(start, end);

        returnVector.push_back(tempVector);
    }
    return returnVector;
}

有没有更惯用的方法来做到这一点? random_access 迭代器的要求向我表明可能有更好的方法。

【问题讨论】:

  • 你应该通过 const 引用传递第一个参数。
  • 其实@PaulMcKenzie,如果你担心性能问题,他最好只对整个类型进行模板,而不是std::vector&lt;T&gt;,然后使用完美转发。
  • @JohnCarter,这个解决方案看起来或多或少没问题。我无法立即想到任何更好的解决方案。我想我会建议让 ?: 运算符更详细(拆分成一个真正的 if 语句),这样它会更清晰一些。
  • 里面有几个多余的typenames。

标签: c++ templates vector idioms


【解决方案1】:

我唯一不同的是如何迭代,以及我们如何附加到结果向量上:

template<typename T> 
std::vector<std::vector<T>> chunkVector(const std::vector<T>& source, size_t chunkSize)
{
    std::vector<std::vector<T>> result;
    result.reserve((source.size() + chunkSize - 1) / chunkSize);

    auto start = source.begin();
    auto end = source.end();

    while (start != end) {
        auto next = std::distance(start, end) >= chunkSize
                    ? start + chunkSize
                    : end;

        result.emplace_back(start, next);
        start = next;
    }

    return result;
}

【讨论】:

  • 我要加result.reserve(source.size() / chunkSize+1);
  • @JonathanWakely 是的,完成了。除了表达方式略有不同。
  • 不错的 C++11 方法。我也总是忘记 std::distance 。
猜你喜欢
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
  • 2018-07-12
  • 2019-07-05
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
相关资源
最近更新 更多