从普通对象数组

时间:2015-07-21 07:43:25

标签: javascript arrays json performance jsonpath

我有一组对象,比如那些:

{
  "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
  • 开头和结尾

3 个答案:

答案 0 :(得分:1)

创建另一个tmp对象作为Hashmap,这样你就可以使用path和id创建一个新的存储键。

逻辑:

  1. 如果路径为_categories,则将其根目录放入sub数组。

  2. 如果没有,检查目标父级是否存在于hashStore中,如果不存在,则创建一个假的,并将其自我定位到目标是_category.path + _category.short_id + '/' attr。

  3. 对于所有元素,按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。

  4. 使用键来确定对象中是否存在对象应该是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。

&#13;
&#13;
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;
&#13;
&#13;