Как использовать `copy_if` для фильтрации `str` конкретного кратного индекса

#c #c 11

#c #c 11

Вопрос:

Как использовать copy_if фильтр str конкретного кратного индекса.

например str , это «1000020000300004000050000», я хочу newStr , чтобы это было «12345».

В соответствии с 1 равно 5 * 0, 2 равно 5 * 1, 3 равно 5 * 2 и т.д.


Исходный код :

 std::string str("1000020000300004000050000");
std::string newStr;

std::copy_if(str.begin(), str.end(),
    std::back_inserter(newStr),
    [] (char c) {
        // Some specific rule I want to return.
        return ...;
    }
);
  

Идеальный код :

 std::copy_if(str.begin(), str.end(),
    std::back_inserter(newStr),
    [] (char c) {
        // I can get the index of iteration.
        return (index % 5 == 0);
    }
);
  

Комментарии:

1. Что не так с простым циклом for?

2. Я хочу знать, можно ли сделать то же самое copy_if или нет. Спасибо за ваш комментарий. 🙂

Ответ №1:

Вы можете передать начало строки и текущий итератор в качестве захвата лямбда-функции и использовать их соответствующим образом (тогда лямбда-выражение должно быть изменяемым):

 std::string str("1000020000300004000050000");
std::string newStr;

std::copy_if(str.begin(), str.end(),
std::back_inserter(newStr),
[it = str.begin(), beg = str.begin()] (auto c) mutable {
    // I can get the index of iteration.
    return (std::distance(it  , beg) % 5 == 0);
}
  

ДЕМОНСТРАЦИЯ

Комментарии:

1. Это интересный способ сделать это. Просто обратите внимание, что для неслучайного accessiterator std::distance имеет линейную сложность (не проблема для данного конкретного случая). Также для общего лямбда-выражения требуется C 14

Ответ №2:

Вы можете отслеживать индекс в локальной переменной. Обратите внимание, что вам нужно захватить i по ссылке. т.е. [amp;i]

 int i = 0;
std::copy_if(str.begin(), str.end(),
    std::back_inserter(newStr),
    [amp;i] (char c) {
        int index = i  ;
        return (index % 5 == 0);
    }
);