我收到了来自网络服务的回复,想要用自定义值替换响应中的某些值。
一种方法是编写树遍历器,然后检查值并替换为我的自定义值
所以响应是这样的:
[
{
"name": "n1",
"value": "v1",
"children": [
{
"name": "n2",
"value": "v2"
}
]
},
{
"name": "n3",
"value": "v3"
}
]
现在我的自定义地图就像这样
const map = {
"v1": "v11",
"v2": "v22",
"v3": "v33"
};
我想要的只是
[
{
"name": "n1",
"value": "v11",
"children": [
{
"name": "n2",
"value": "v22"
}
]
},
{
"name": "n3",
"value": "v33"
}
]
我在想是否可以对我的响应进行字符串化,然后使用我的值映射中的自定义构建正则表达式替换值。
有点像这样
originalString.replace(regexp,function(replacement))
答案 0 :(得分:3)
树遍历 更快
请注意,在正则表达式实现中可以更有效地完成某些操作,但我仍然认为还有一些瓶颈需要解释。
为什么正则表达式很慢:
为什么正则表达式较慢可能还有很多原因,但我会解释至少一个重要原因:
当您使用正则表达式进行查找和替换时,您每次都会使用创建新字符串并每次都执行匹配。正则表达式can be very expensive和我的实现并不特别便宜。
为什么树遍历更快:
在树遍历中,我直接改变对象。这并不需要创建新的string
对象或任何新对象。我们每次也都没有对整个字符串执行完整搜索。
<强>结果
运行下面的性能测试。使用console.time
进行测试以记录所需的时间。看树遍历要快得多。
function usingRegex(obj, map) {
return JSON.parse(Object.keys(map).map(oldValue => ({
oldValue,
newValue: map[oldValue]
})).reduce((json, {
oldValue,
newValue
}) => {
return json.replace(
new RegExp(`"value":"(${oldValue})"`),
() => `"value":"${newValue}"`
);
}, JSON.stringify(obj)));
}
function usingTree(obj, map) {
function traverse(children) {
for (let item of children) {
if (item && item.value) {
// get a value from a JS object is O(1)!
item.value = map[item.value];
}
if (item && item.children) {
traverse(item.children)
}
}
}
traverse(obj);
return obj; // mutates
}
const obj = JSON.parse(`[
{
"name": "n1",
"value": "v1",
"children": [
{
"name": "n2",
"value": "v2"
}
]
},
{
"name": "n3",
"value": "v3"
}
]`);
const map = {
"v1": "v11",
"v2": "v22",
"v3": "v33"
};
// show that each function is working first
console.log('== TEST THE FUNCTIONS ==');
console.log('usingRegex', usingRegex(obj, map));
console.log('usingTree', usingTree(obj, map));
const iterations = 10000; // ten thousand
console.log('== DO 10000 ITERATIONS ==');
console.time('regex implementation');
for (let i = 0; i < iterations; i += 1) {
usingRegex(obj, map);
}
console.timeEnd('regex implementation');
console.time('tree implementation');
for (let i = 0; i < iterations; i += 1) {
usingTree(obj, map);
}
console.timeEnd('tree implementation');
&#13;
答案 1 :(得分:1)
与树遍历相比,它会更快吗?
我不知道。我认为这取决于输入的大小和替换地图的大小。您可以在JSPerf.com处运行一些测试。
如果是,我应该怎么做?
如果要替换的值不需要任何特殊的转义或其他什么,那么使用基于正则表达式的字符串替换相当容易。像这样:
const input = [
{
"name": "n1",
"value": "v1",
"children": [
{
"name": "n2",
"value": "v2"
}
]
},
{
"name": "n3",
"value": "v3"
}
];
const map = {
"v1": "v11",
"v2": "v22",
"v3": "v33"
};
// create a regex that matches any of the map keys, adding ':' and quotes
// to be sure to match whole property values and not property names
const regex = new RegExp(':\\s*"(' + Object.keys(map).join('|') + ')"', 'g');
// NOTE: if you've received this data as JSON then do the replacement
// *before* parsing it, don't parse it then restringify it then reparse it.
const json = JSON.stringify(input);
const result = JSON.parse(
json.replace(regex, function(m, key) { return ': "' + map[key] + '"'; })
);
console.log(result);
答案 2 :(得分:0)
绝对遍历变得更快,因为字符串替换意味着对最终字符串中的每个字符进行移动,而不是迭代器可以跳过不一定的项目。