我有一组对象,比如那些:
{
"short_id": "2p45q",
"path": "/",
"name": {
"en-US": "IndustrialDesign"
}
}
...
{
"short_id": "2q56r",
"path": "/2p45q/",
"name": {
"en-US": "Automotive"
}
}
我必须遍历数组的每个元素并检查path
,然后找到该元素的 parent 并将其推送到该父级的新数组属性{{1 }}。每个孩子都可以拥有sub
属性,因此是更多孩子的父母。最终结果(对于此示例)将如下所示:
sub
我有一个有效的代码(使用this jsonpath lib):
{
"short_id": "2p45q",
"path": "/",
"name": {
"en-US": "Test A"
},
"sub": [
{
"short_id": "2q56r",
"path": "/2p45q/",
"name": {
"en-US": "Test A.1"
}
}
]
}
但性能非常糟糕,主要是因为我每次迭代都会查询整个数组。
我的问题是如何优化代码?
注意:
function(categories) {
var _categories = [];
angular.forEach(angular.copy(categories), function(_category) {
if (_category.path === "/") {
_categories.push(_category);
} else {
var _path = _category.path.split("/");
_path.pop();
var _parent = _path.pop();
jsonpath.apply(_categories, "$..[?(@.short_id=='" + _parent + "')]", function(obj) {
if(!obj.hasOwnProperty("sub")) {
obj.sub = [];
}
obj.sub.push(_category);
return obj;
});
}
});
return _categories;
}
正好是5个字符。short_id
中的每个字符都可以是short_id
[0-9a-z]
保证以path
答案 0 :(得分:1)
创建另一个tmp对象作为Hashmap,这样你就可以使用path和id创建一个新的存储键。
逻辑:
如果路径为_categories
,则将其根目录放入sub
数组。
如果没有,检查目标父级是否存在于hashStore中,如果不存在,则创建一个假的,并将其自我定位到目标是_category.path + _category.short_id + '/'
attr。
对于所有元素,按sub
创建一个密钥,并检查它是否存在于hashStore中,如果存在,那么存储中的那个应该是假的,从假冒中获取function buildTree(categories) {
var _categories = [];
var store = {};
angular.forEach(angular.copy(categories), function(_category) {
if (_category.path === '/') {
_categories.push(_category);
} else {
var target;
// If parent exist
if (typeof store[_category.path] !== 'undefined') {
// Check parent have sub or not, if not, create one.
target = store[_category.path];
if (typeof store[_category.path].sub === 'undefined') {
target.sub = [];
}
} else {
// Create fake parent.
target = {sub: []};
store[_category.path] = target;
}
// Push to parent's sub
target.sub.push(_category);
}
// Create key map
var key = _category.path + _category.short_id + '/';
// If fake object exist, get its sub;
if (typeof store[key] !== 'undefined') {
_category.sub = store[key].sub;
}
store[key] = _category;
});
return _categories;
}
。然后通过创建的密钥将自己分配给hashStore。
使用键来确定对象中是否存在对象应该是O(1)。 所以这个函数的性能应该是O(n),而n是原始列表中元素的数量。
bool hascycle (graph * mygraph, int start, bool visited[])
{
stack <pair<int, int> > mystack;
mystack.push(make_pair(start, -1));
visited[start] = true;
while (!mystack.empty())
{
int v = mystack.top().first;
int f = mystack.top().second;
mystack.pop();
const auto &edges = mygraph->edges[v];
for (auto it = edges.begin(); it != edges.end(); it++)
{
int w = *it;
if (!visited[w])
{
mystack.push(make_pair(w, v));
visited[w] = true;
}
else if (w != f)
return true;
}
}
return false;
}
答案 1 :(得分:1)
此解决方案更灵活,因为它不需要知道路径长度或与short_id
的相关性
var source = [{
"short_id": "2p45q",
"path": "/",
"name": {
"en-US": "IndustrialDesign"
}
}, {
"short_id": "2q56r",
"path": "/2p45q/",
"name": {
"en-US": "Automotive"
}
}];
function buildTree(arr) {
var source = arr.slice();
source.sort(function(a, b) {
return a.path.length <= b.path.length;
});
var tree = source.splice(0, 1)[0];
tree.subo = {};
source.forEach(function(i) {
var re = /[^\/]*\//g;
var context = tree;
while ((m = re.exec(i.path.substr(1))) !== null) {
if (context.subo[m[0]] === undefined) {
context.subo[m[0]] = i;
i.subo = {};
return;
}
context = context.subo[m[0]];
}
});
(function subOsub(i) {
var keys = Object.keys(i.subo);
if (keys.length > 0) {
i.sub = [];
for (var j = 0; j < keys.length; j++) {
i.sub.push(i.subo[keys[j]]);
subOsub(i.subo[keys[j]]);
}
}
delete i.subo;
})(tree);
return tree;
}
alert(JSON.stringify(buildTree(source), null, ' '));
答案 2 :(得分:1)
好吧,只需检查每个对象的路径以查看放置它的位置。 您只需要路径到对象的映射。 E.g。
var objs = [
{
"short_id": "2p45q",
"path": "/",
"name": {
"en-US": "IndustrialDesign"
}
},
{
"short_id": "blah",
"path": "/2p45q/foo/",
"name": {
"blah": "blah"
}
},
{
"short_id": "2q56r",
"path": "/2p45q/",
"name": {
"en-US": "Automotive"
}
}
];
// map paths to objects (one iteration)
var path_to_obj = {};
objs.forEach(function(obj){
path_to_obj[obj.path] = obj;
});
// add objects to the sub array of their parent (one iteration)
objs.forEach(function(obj){
var parentpath = obj.path.replace(/[^\/]*\/$/, '');
var parent = path_to_obj[parentpath];
if(parent){
parent.sub = parent.sub || [];
parent.sub.push(obj);
}
});
var pre = document.createElement('pre');
pre.innerHTML = 'Result:\n' + JSON.stringify(path_to_obj['/'], null, 4);
document.body.appendChild(pre);
&#13;