我以name:key:dataLength:data
的格式编码,这些字符串通常可以链接在一起。例如"aNum:n:4:9879aBool:b:1:taString:s:2:Hi"
这会映射到一个类似的对象:
{
aNum: 9879,
aBool: true,
aString: "Hi"
}
我有一种解析这种格式的字符串的方法,但是我不确定是否使用substring
是处理字符串的最有效方法,是否有一种更有效的方法来处理字符串时尚(反复砍掉前面部分):
Map<string, dynamic> fromString(String s){
Map<String, dynamic> _internal = new Map();
int start = 0;
while(start < s.length){
int end;
List<String> parts = new List<String>(); //0 is name, 1 is key, 2 is data length, 3 is data
for(var i = 0; i < 4; i++){
end = i < 3 ? s.indexOf(':') : num.parse(parts[2]);
parts[i] = s.substring(start, end);
start = i < 3 ? end + 1 : end;
}
var tranType = _tranTypesByKey[parts[1]]; //this is just a map to an object which has a function that can convert the data section of the string into an object
_internal[parts[0]] = tranType._fromStr(parts[3]);
}
return _internal;
}
答案 0 :(得分:1)
我会尝试s.split(':')
并处理结果列表。
如果你做了很多这样的操作,你应该考虑创建基准测试,尝试不同的技术并进行比较。
如果你仍然需要这一行
s = i < 3 ? s.substring(idx + 1) : s.substring(idx);
我会避免在每次迭代中创建一个新的子字符串,而只是跟踪next
位置。
答案 1 :(得分:1)
您必须确定性能相对于代码的可读性和可维护性的重要程度。
那就是说,你不应该反复切断琴弦的头部。这保证是低效的 - 你的字符串中的记录数量需要时间是二次的,只需要创建那些尾部字符串。
对于解析每个字段,您可以避免在长度和类型字段上执行子字符串。对于长度字段,您可以自己构建数字:
int index = ...;
// index points to first digit of length.
int length = 0;
int charCode = source.codeUnitAt(index++);
while (charCode != CHAR_COLON) {
length = 10 * length + charCode - 0x30;
charCode = source.codeUnitAt(index++);
}
// index points to the first character of content.
由于长度通常是小整数(小于2 <&lt; 31),因此这可能比创建子字符串并调用int.parse更有效。
类型字段是单个ASCII字符,因此您可以使用codeUnitAt
来获取其ASCII值而不是创建单字符字符串(然后您的内容解释查找将需要打开字符代码而不是字符串)。
对于解析内容,您可以传递源字符串,启动索引和长度,而不是创建子字符串。然后布尔解析器也可以只读取代码单元而不是单例字符串,字符串解析器只能创建子字符串,数字解析器也可能必须创建子字符串并调用double.parse。
如果Dart有一个double.parseSubstring(source,[int from = 0,int to])可以将子字符串解析为double而不创建子字符串,那将会很方便。