设计思路
- 递归遍历:采用递归的方式遍历文档的每一个层级,无论是对象还是数组,都要深入到最底层。
- 类型判断与转换:在遍历过程中,判断当前元素的类型,如果是指定类型(如字符串表示的日期),则进行相应的转换。
- 性能优化:
- 减少递归深度:尽量减少不必要的递归调用,对于已经处理过的子结构,避免重复处理。
- 缓存处理结果:对于相同结构的子文档,缓存其转换结果,下次遇到直接使用。
- 批量处理:如果可能,将多个文档一起处理,利用批量操作的优势。
实现代码(以JavaScript为例)
function convertDate(str) {
return new Date(str);
}
function mapRecursive(obj, type, converter) {
if (Array.isArray(obj)) {
return obj.map(item => mapRecursive(item, type, converter));
} else if (typeof obj === 'object' && obj!== null) {
const newObj = {};
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
newObj[key] = mapRecursive(obj[key], type, converter);
}
}
return newObj;
} else if (typeof obj === type) {
return converter(obj);
}
return obj;
}
// 使用示例
const complexDoc = {
data: [
{
subData: [
{ date: '2023-10-01' },
{ date: '2023-10-02' }
]
}
]
};
const newDoc = mapRecursive(complexDoc,'string', convertDate);
console.log(newDoc);
性能优化点
- 减少递归调用:可以通过迭代方式替代递归,使用栈数据结构模拟递归过程,避免因递归过深导致栈溢出问题。例如:
function mapIterative(obj, type, converter) {
const stack = [obj];
const result = JSON.parse(JSON.stringify(obj));
const stackResult = [result];
while (stack.length > 0) {
const current = stack.pop();
const currentResult = stackResult.pop();
if (Array.isArray(current)) {
for (let i = 0; i < current.length; i++) {
stack.push(current[i]);
stackResult.push(currentResult[i]);
}
} else if (typeof current === 'object' && current!== null) {
for (const key in current) {
if (Object.hasOwnProperty.call(current, key)) {
stack.push(current[key]);
stackResult.push(currentResult[key]);
}
}
} else if (typeof current === type) {
stackResult[stackResult.length - 1] = converter(current);
}
}
return result;
}
- 缓存处理结果:可以使用一个
WeakMap
来缓存已经处理过的对象,避免重复处理。
const cache = new WeakMap();
function mapWithCache(obj, type, converter) {
if (cache.has(obj)) {
return cache.get(obj);
}
if (Array.isArray(obj)) {
const newArray = obj.map(item => mapWithCache(item, type, converter));
cache.set(obj, newArray);
return newArray;
} else if (typeof obj === 'object' && obj!== null) {
const newObj = {};
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
newObj[key] = mapWithCache(obj[key], type, converter);
}
}
cache.set(obj, newObj);
return newObj;
} else if (typeof obj === type) {
return converter(obj);
}
return obj;
}
- 批量处理:如果有多个文档,可以将它们合并处理,然后再拆分结果,减少总的处理次数。例如:
function batchMap(docs, type, converter) {
const combined = { docs: docs };
const processed = mapRecursive(combined, type, converter);
return processed.docs;
}