Как я могу улучшить следующую лямбда-функцию для поиска первых 4 элементов в векторе - PullRequest
0 голосов
/ 18 марта 2020

На практике я пытаюсь скопировать первые 4 записи, отличные от 2, из вектора целых чисел, используя copy_if.

Кажется, это работает, но если есть лучший способ написания этой лямбды, тогда я ' Я хотел бы научиться правильно. Ура.

   vector<int> first_vector = {2,8,50,2,4,5,9,12};
   vector<int> second_vector (first_vector.size());
   int count_elem=0;
   auto it = copy_if(first_vector.begin(),first_vector.end(),second_vector.begin(),
            [&count_elem]
            (int i){
                  if(i!=2 && count_elem!=4)
                  {
                      count_elem++;
                      return 1;
                  }
                  return 0;});

Ответы [ 2 ]

2 голосов
/ 18 марта 2020

Поскольку вы не копируете все значения из first_vector в second_vector, вам не следует инициализировать second_vector для хранения того же количества элементов, что и first_vector. Вы создаете больше элементов, чем хотите, где дополнительные элементы инициализируются значением 0.

. Я бы предложил reserve() с размером second_vector вместо этого и затем использовал бы std::back_inserter в качестве конечного итератора для копирования. Таким образом, second_vector заканчивается только теми значениями, которые вы хотите передать, и ничего больше.

Это также устранит необходимость в переменной count_elem. Вы можете использовать second_vector.size(), чтобы узнать, сколько значений было помещено в вектор.

std::vector<int> first_vector = {2, 8, 50, 2, 4, 5, 9, 12};
std::vector<int> second_vector;
second_vector.reserve(4);
std::copy_if(
    first_vector.begin(), first_vector.end(),
    std::back_inserter(second_vector),
    [&](int i){
        return ((i != 2) && (second_vector.size() < 4));
    }
);

Обратите внимание, однако, что использование std::copy_if() будет проходить через весь first_vector, оно будет не прекращайте итерацию, если 4 значения были переданы в second_vector. Вместо этого было бы эффективнее просто запустить свой собственный l oop, чтобы вы могли сломать его как можно скорее:

std::vector<int> first_vector = {2, 8, 50, 2, 4, 5, 9, 12};
std::vector<int> second_vector;
second_vector.reserve(4);
for(int i : first_vector) {
    if (i != 2) {
        second_vector.push_back(i);
        if (second_vector.size() == 4)
            break;
    }
}
0 голосов
/ 18 марта 2020
auto it = copy_if(first_vector.begin(),first_vector.end(),second_vector.begin(),
            [&count_elem](int i){return (i!=2 && count_elem !=4 && count_elem++!=4);});

Обратите внимание, что в вашем коде у вас будут дополнительные элементы во втором векторе, но используйте reserve, чтобы избежать выделения.

Вы можете использовать std::back_inserter, чтобы избежать этого, как показано ниже

#include <vector>
#include <algorithm>
#include <iostream>
int main( ) {
    std::vector<int> first_vector = {2,8,50,2,4,5,9,12};
    std::vector<int> second_vector;
    second_vector.reserve(4);
    int count_elem=0;
    copy_if(first_vector.begin(),first_vector.end(),std::back_inserter(second_vector),[&count_elem] (int i){ return i!=2 && count_elem !=4 && count_elem++!=4;});
    for(auto const & e:second_vector) std::cout<<e<<" ";
}
...