Reputation: 1074
I have the following strings:
std::string str1 = "1234567890";
std::string str2 = "B-XXXX_XXX_V-XX_X";
I want to loop through str2
and replace every occurrence of X with the subsequent value from str1
, resulting in: B-1234_567_V-89_0
.
I have a semblance of a solution below, but it's not very efficient (it worked at one point). In brief, I tried to loop through the characters in str2
, and if the character equaled 'X', replace that character with an incrementing index from 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++;
}
}
What is the most efficient way to perform this operation?
Upvotes: 3
Views: 1637
Reputation: 75698
The only problem I see with your code is that you unnecessary use 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;
}
Upvotes: 0
Reputation: 4049
If by "not very efficient" you want to improve your current code, maybe the only thing to do is to rewrite your loop:
int idx = 0;
for (char& c : str2) {
if (c == 'X')
c = str1[idx++];
}
But if you want to write this by only using standard library, you can do the same thing by using 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;
}
Upvotes: 1
Reputation: 60218
Here's another solution:
auto i = str1.begin();
for (char& ch: str2) {
if (ch == 'X')
ch = *i++;
Upvotes: 0
Reputation: 372764
Your current implementation treats each individual unit of the string as a std::string
rather than as a single char
, which introduces some unnecessary overhead. Here's a rewrite that uses 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++;
}
}
You can improve readability by using a range-based for loop, like this:
int x_ind = 0;
for (char& ch: str2) {
if (ch == 'X') {
ch = str1[x_ind];
x_ind++;
}
}
Upvotes: 3