首页 > 解决方案 > 如何替换向量中的序列

问题描述

假设我有以下向量:

std::vector<int> data{0,1,2,3,4};

我想用一个数字替换序列 {1,2,3}。我找到了一个带有 std::replace 的示例,但是有一个数字被其他单个数字替换。如何替换向量中的序列?

标签: c++c++11

解决方案


通过使用迭代器对而不是向量作为输入,我已将您的问题推广到任何 STL 容器中。该算法有3个步骤:

  1. 通过std::search查找序列。last没找到就返回
  2. 用新值替换第一个序列项
  3. 使用std::remove_if删除剩余项目

由于迭代器不能真正从容器中删除项目,data.erase(newEnd, data.end());因此需要调用来缩小向量。

算法应该非常稳定,甚至适用于 1 元素向量。constexpr从 C++14 开始可以声明函数。

#include <algorithm>
#include <iostream>
#include <vector>

template <class ForwardIt1, class ForwardIt2, class Value>
constexpr ForwardIt1 replaceSequenceWithValue(ForwardIt1 first, ForwardIt1 last, 
                                              ForwardIt2 s_first, ForwardIt2 s_last,
                                              Value &&value) {
  auto seq_start = std::search(first, last, s_first, s_last);
  if (seq_start == last)
    return last; // return last if no seq was found

  *seq_start = std::forward<Value>(value);

  auto itemsToBeRemoved = std::distance(s_first, s_last) - 1;

  // return new end
  if (itemsToBeRemoved > 0)
    return std::remove_if(std::next(seq_start), last,
                          [&itemsToBeRemoved](const auto &) { return itemsToBeRemoved-- > 0; });
  return last;
}


int main() {
  std::vector<int> data{0, 1, 2, 3, 4};
  std::vector<int> seq{1, 2, 3};
  auto newEnd = replaceSequenceWithValue(data.begin(), data.end(), seq.begin(), seq.end(), 5);
  data.erase(newEnd, data.end());
  for (auto d : data) {
    std::cout << d << '\n';
  }
}

如果您不需要这样的概括,您可以将其包装成具有更简单签名的函数:

template <class Value>
constexpr void replaceSequenceWithValue(std::vector<Value> &data, const std::vector<Value> &sequence, Value &&value) {
  auto newEnd = replaceSequenceWithValue(data.begin(), data.end(), sequence.begin(),
                                         sequence.end(), std::forward<Value>(value));
  data.erase(newEnd, data.end());
}

并使用如下:

int main() {
  std::vector<int> data{0, 1, 2, 3, 4};
  replaceSequenceWithValue(data, {1, 2, 3}, 5);
  for (auto d : data) {
    std::cout << d << '\n';
  }
}

推荐阅读