Daniel
Daniel

Reputation: 2592

Replace all occurrences based on map

This question might have already been answered but I haven't found it yet.

Let's say I have a std::map<string,string> which contains string pairs of <replace_all_this, to_this>.

I checked Boost's format library, which is close but not perfect:

std::map<string,string> m;
m['$search1'] = 'replace1';
m['$search2'] = 'replace2';
format fmter1("let's try to %1% and %2%.");
fmter % 36; fmter % 77;
for(auto r : m) {
  fmter % r.second;
}
// would print "let's try to replace1 and replace2

This would work, but I lose control of what. Actually I'd like to have this as result:

format fmter1("let's try to $search2 and $search1 even if their order is different in the map.");
...
//print: "let's try to replace2 and replace1 even if their order is different in the map".

Please note: map can contain more items, and items can occur multiple times in the formatter.

What is the way to go for this in 2020, I'd like it to be effective and fast, so I'd avoid iterating over the map multiple times.

Upvotes: 0

Views: 81

Answers (1)

Alexis Wilke
Alexis Wilke

Reputation: 20720

There may be new libraries but there is no new algorithm to do that faster than what we have so far.

Assuming your format implies a $<name> for your variables, you can search for the first '$', read the <name> search for that in the map, then do the replace. This allows you to either skip the replacement or process it too (i.e. make it recursive where a variable can reference another).

I don't think that doing it the other way around would be any faster: i.e. go through the map and search for the names in the string means you'd be parsing the strings many times and if you have many variables, it will be a huge waste if most are not likely part of your string. Also if you want to prevent some level of recursivity, it's very complicated.

Where you can eventually optimize is in calculating the size of the resulting string and allocate that buffer once instead of using += which is not unlikely going to be slower.

I have such an implementation in my snaplogger. The variable has to be between brackets and it can include multiple parameters to further tweak the data. There is documentation here about what is supported by that function and as written, you can easily extend the class to add more features. It's probably not a one to one match to what you're looking for, but it shows you that there is not 20 ways of implementing that function.

Upvotes: 1

Related Questions