【问题标题】:How to Transfer Elements that Match a Predicate from One Vector to Another in C++?如何在 C++ 中将匹配谓词的元素从一个向量转移到另一个向量?
【发布时间】:2021-04-28 23:03:51
【问题描述】:

给定两个可复制元素的向量和对这些项目的谓词,什么是有效且惯用的方法:

  1. 从第一个向量中删除匹配项
  2. 将匹配项附加到第二个向量

下面的 sn-p 反映了我目前的想法,但它确实需要对源向量进行两次传递。

vector<int> source{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
vector<int> target;

auto predicate = [](int n) { return n % 2 == 0; };

std::for_each(source.begin(), source.end(), [&predicate, &target](int n) {
    if (predicate(n)) {
        target.push_back(n);
    }
});

auto it = std::remove_if(source.begin(), source.end(), predicate);
source.erase(it, source.end());

【问题讨论】:

    标签: c++ algorithm vector stl std


    【解决方案1】:

    我会使用std::partitionsource 分成两部分。

    auto itr = std::partition(source.begin(), source.end(), predicate);
    
    target.insert(target.end(), itr, source.end());
    
    source.resize(itr - source.begin());
    

    如果顺序需要保持不变,请使用stable_partition

    【讨论】:

    • 我认为虽然target 在原始问题的示例中以空开头,但代码应该可以通过附加到target 来工作,即使它已经有一些内容。
    • 那么你可以插入目标而不是构造targettarget.insert(target.end(), itr, source.end())
    • int 无关,但如果这是未知类型,我会使用std::move_iterators 进行插入
    • @OP:请注意,如果您只使用迭代器,您可能不再需要额外的向量,而只需使用分区向量。
    • 要清楚,这里的上下文是源向量和目标向量都是长期存在的,并且都早于和晚于这个特定的操作。
    【解决方案2】:

    我同意 @acraig5075 的观点,即 stable_partition,然后复制和擦除会做你想做的事。

    但是,如果您不想在源容器中随机播放元素(可能是徒劳的愿望,恕我直言),您可以循环执行:(未经测试的代码)

    auto itr = source.begin();
    while (itr != source.end()) {
       if (predicate(*itr)) {
          target.push_back(*itr);
          itr = source.erase(itr);
       } else
          ++itr;
    }
    

    请注意,当元素移动到 target 时,这将一次“滑下”元素的元素,这就是为什么我认为避免这样做可能是愚蠢的。 (注意:如果您使用的是list,那么就不会那么愚蠢了)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      相关资源
      最近更新 更多