I was recently talking to someone about a function I wrote to mimic (very basically) the string interpolation function String.Format()
found in the C# language. They mentioned that I would have performance concerns using RegExp, and that I should try to parse the string template rune by rune. So I wrote a loop the best I could to accomplish that very task. It looks alarmingly ugly (to me) and I wanted some input on the performance considerations with the loop version. As well, maybe some better suggestions on how to accomplish this function in a more sensible/clean fashion.
Here's the two different versions of the implementation:
void main() {
String thestring = '{0} {1} {2} {3}!';
assert(formatStringListRegExp([thestring, 'This', 'was', 'a', 'triumph']) == 'This was a triumph!');
assert(formatStringListloop([thestring, 'This', 'was', 'a', 'triumph']) == 'This was a triumph!');
}
String formatStringListRegExp(List<String> args)
{
if (args == null || args.length < 2) {
throw new ArgumentError('expected at least two paramters.');
}
if (args[0] is !String) {
throw new ArgumentError('expected a string for the first paramter.');
}
var str = args[0];
var inserts = args.sublist(1);
for (var i = 0; i < inserts.length; i++) {
str = str.replaceAll('{$i}', inserts[i].toString());
}
return str;
}
String formatStringListLoop(List<String> args)
{
if (args == null || args.length < 2) {
throw new ArgumentError('expected at least two paramters.');
}
if (args[0] is !String) {
throw new ArgumentError('expected a string for the first paramter.');
}
var str = args[0];
var inserts = args.sublist(1);
StringBuffer buffer = new StringBuffer();
for (var i = 0; i < str.length; i++) {
if (str[i] == '{' && i < str.length + 1) {
var value = '';
var count = 1;
var number;
while(true) {
if (i + count < str.length - 1) {
try {
number = int.parse(str[i + count]);
} catch (e) {
break;
}
} else {
break;
}
if (number is int) {
value += number.toString();
count++;
} else {
break;
}
}
if (str[i + count] == '}') {
if (value.isNotEmpty) {
int index = int.parse(value);
if (index < inserts.length) {
buffer.write(inserts[index]);
i += count;
} else {
buffer.write('{');
}
}
}
} else {
buffer.write(str[i]);
}
}
return buffer.toString();
}