我有一个平面的目录列表:
var directories = [
{ path: '/a', status: 0 },
{ path: '/a/a', status: 1 },
{ path: '/a/b', status: 1 },
{ path: '/a/c', status: 0 },
{ path: '/b', status: 0 },
{ path: '/b/a', status: 0 },
{ path: '/b/b', status: 1 },
{ path: '/c', status: 0 },
{ path: '/c/a', status: 2 },
{ path: '/c/b', status: 0 },
{ path: '/c/c', status: 1 },
{ path: '/c/d', status: 1 },
{ path: '/d', status: 0 },
{ path: '/d/a', status: 1 },
{ path: '/e', status: 1 },
{ path: '/e/a', status: 0 }
];
我希望每个目录的子女总数和这些孩子的总数按例如他们的状态编号。
{ path: '/a', status: 0, child_total: 3, child_status-0: 1, child_status-1: 2 }
我认为最好的方法是创建一个包含命名路径的Object,然后循环遍历目录的每个父目录,并为每个目录添加一个。
使用这种方法我创建了这些函数:
function increment(item, attr) {
if (!item[attr]) { item[attr] = 0; }
item[attr] += 1;
};
function calculate(items) {
var i = 0;
var list = {};
// for each directory
for (i = 0; i < items.length; i += 1) {
// if the directory stats already exist, merge in directory info
list[items[i].path] = list[items[i].path] ? Object.assign(list[items[i].path], items[i]) : items[i];
var j = 0;
var parts = items[i].path.split('/');
var path = '';
// loop through it's parents
for (j = 1; j < parts.length; j += 1) {
path += '/' + parts[j];
// increment the parent's totals
if (path !== items[i].path) {
if (!list[path]) { list[path] = {}; }
increment(list[path], 'child_total');
increment(list[path], 'child_status-' + items[i].status);
}
}
}
return list;
}
这是一个工作小提琴:
https://jsfiddle.net/kmturley/b955d3mb/1/
这是我想要使用结构的目录浏览器:
https://jsfiddle.net/kmturley/x93pcd60/
我打算在数千个项目上运行此功能,因此性能非常重要。我想知道这是否是最佳方法?
有更好的方法吗?循环中没有循环?也许是RegEx用于分割路径?
任何建议都会有所帮助!
答案 0 :(得分:0)
有更好的方法吗?循环中没有循环?也许是RegEx for 拆分路径?
不确定如何确定“更好的方式”。只有你能做出这样的决定。
您可以使用Array.prototype.reduce()
迭代原始数组中的每个对象,在对象上生成有关对象的数据。
替换statuses
数组,其中property是当前路径,status
是当前对象的status
,用于child_status-0: 1, child_status-N: 2
属性。
var directories = [
{ path: '/a', status: 0 },
{ path: '/a/a', status: 1 },
{ path: '/a/b', status: 1 },
{ path: '/a/c', status: 0 },
{ path: '/b', status: 0 },
{ path: '/b/a', status: 0 },
{ path: '/b/b', status: 1 },
{ path: '/c', status: 0 },
{ path: '/c/a', status: 2 },
{ path: '/c/b', status: 0 },
{ path: '/c/c', status: 1 },
{ path: '/c/d', status: 1 },
{ path: '/d', status: 0 },
{ path: '/d/a', status: 1 },
{ path: '/e', status: 1 },
{ path: '/e/a', status: 0 }
];
let pathData = directories.reduce((paths, {path, status}) => {
let dir = new URL("http://mock" + path);
let pathnames = dir.pathname.match(/[^/]+/g);
let _path = pathnames[0];
if (!paths.hasOwnProperty(_path)) {
paths[_path] = {child_total:0, statuses:[]}
}
paths[_path].statuses.push({[dir.pathname]:status});
if (pathnames.length > 1) {
paths[_path].child_total += 1;
};
return paths;
}, {});
console.log(pathData);