如何有效地用另一个 std::string 中的迭代值替换 std::string 中的字符?
How to efficiently replace characters in an std::string with iterative values from another std::string?
我有以下字符串:
std::string str1 = "1234567890";
std::string str2 = "B-XXXX_XXX_V-XX_X";
我想遍历 str2
并将每次出现的 X 替换为 str1
中的后续值,结果是:B-1234_567_V-89_0
。
我有一个类似下面的解决方案,但它不是很有效(它在某一时刻起作用)。简而言之,我尝试遍历 str2
中的字符,如果字符等于 'X',则用 str1
:
的递增索引替换该字符
int ind = 0;
std::string pattern_char;
for (int i = 0; i < str2.size(); i++) {
pattern_char = str2[i];
if (pattern_char == "X") {
str2[i] = str1[x_ind];
x_ind++;
}
}
执行此操作最有效的方法是什么?
您当前的实现将字符串的每个单独单元视为 std::string
而不是单个 char
,这会引入一些不必要的开销。这是使用 char
s:
的重写
int x_ind = 0;
for (int i = 0; i < str2.size(); i++) {
if (str2[i] == 'X') { // Don't assign str2[i] to a char; use character literals
str2[i] = str1[x_ind];
x_ind++;
}
}
您可以使用基于范围的 for 循环来提高可读性,如下所示:
int x_ind = 0;
for (char& ch: str2) {
if (ch == 'X') {
ch = str1[x_ind];
x_ind++;
}
}
我在您的代码中看到的唯一问题是您不必要地使用 std::string pattern_char;
:
#include <string>
#include <iostream>
#include <stdexcept>
auto replace_with_pattern(std::string& str, char ch_to_replace, const std::string& pattern)
{
auto pattern_it = pattern.begin();
for (char& ch : str)
{
if (ch == ch_to_replace)
{
if (pattern_it == pattern.end())
throw std::invalid_argument{"ran out of pattern"};
ch = *pattern_it;
++pattern_it;
}
}
}
int main()
{
std::string str1 = "1234567890";
std::string str2 = "B-XXXX_XXX_V-XX_X";
replace_with_pattern(str2, 'X', str1);
std::cout << str2 << std::endl;
}
如果 "not very efficient" 你想改进你当前的代码,也许唯一要做的就是重写你的循环:
int idx = 0;
for (char& c : str2) {
if (c == 'X')
c = str1[idx++];
}
但是如果你只想使用标准库来写这个,你可以使用 std::transform()
:
来做同样的事情
#include <algorithm>
#include <iostream>
#include <string>
int main()
{
std::string str1 = "1234567890";
std::string str2 = "B-XXXX_XXX_V-XX_X";
int i = 0;
std::transform(str2.begin(), str2.end(), str2.begin(),
[&str1, &i](const char& c) -> char {
return c == 'X' ? str1[i++] : c;
});
std::cout << str2 << std::endl;
}
这是另一个解决方案:
auto i = str1.begin();
for (char& ch: str2) {
if (ch == 'X')
ch = *i++;
我有以下字符串:
std::string str1 = "1234567890";
std::string str2 = "B-XXXX_XXX_V-XX_X";
我想遍历 str2
并将每次出现的 X 替换为 str1
中的后续值,结果是:B-1234_567_V-89_0
。
我有一个类似下面的解决方案,但它不是很有效(它在某一时刻起作用)。简而言之,我尝试遍历 str2
中的字符,如果字符等于 'X',则用 str1
:
int ind = 0;
std::string pattern_char;
for (int i = 0; i < str2.size(); i++) {
pattern_char = str2[i];
if (pattern_char == "X") {
str2[i] = str1[x_ind];
x_ind++;
}
}
执行此操作最有效的方法是什么?
您当前的实现将字符串的每个单独单元视为 std::string
而不是单个 char
,这会引入一些不必要的开销。这是使用 char
s:
int x_ind = 0;
for (int i = 0; i < str2.size(); i++) {
if (str2[i] == 'X') { // Don't assign str2[i] to a char; use character literals
str2[i] = str1[x_ind];
x_ind++;
}
}
您可以使用基于范围的 for 循环来提高可读性,如下所示:
int x_ind = 0;
for (char& ch: str2) {
if (ch == 'X') {
ch = str1[x_ind];
x_ind++;
}
}
我在您的代码中看到的唯一问题是您不必要地使用 std::string pattern_char;
:
#include <string>
#include <iostream>
#include <stdexcept>
auto replace_with_pattern(std::string& str, char ch_to_replace, const std::string& pattern)
{
auto pattern_it = pattern.begin();
for (char& ch : str)
{
if (ch == ch_to_replace)
{
if (pattern_it == pattern.end())
throw std::invalid_argument{"ran out of pattern"};
ch = *pattern_it;
++pattern_it;
}
}
}
int main()
{
std::string str1 = "1234567890";
std::string str2 = "B-XXXX_XXX_V-XX_X";
replace_with_pattern(str2, 'X', str1);
std::cout << str2 << std::endl;
}
如果 "not very efficient" 你想改进你当前的代码,也许唯一要做的就是重写你的循环:
int idx = 0;
for (char& c : str2) {
if (c == 'X')
c = str1[idx++];
}
但是如果你只想使用标准库来写这个,你可以使用 std::transform()
:
#include <algorithm>
#include <iostream>
#include <string>
int main()
{
std::string str1 = "1234567890";
std::string str2 = "B-XXXX_XXX_V-XX_X";
int i = 0;
std::transform(str2.begin(), str2.end(), str2.begin(),
[&str1, &i](const char& c) -> char {
return c == 'X' ? str1[i++] : c;
});
std::cout << str2 << std::endl;
}
这是另一个解决方案:
auto i = str1.begin();
for (char& ch: str2) {
if (ch == 'X')
ch = *i++;