基于条件的数组中的双向搜索--javascript

时间:2015-12-17 20:02:27

标签: javascript arrays

我有2个阵列A和B:

"A": [{
       "name": "test1",
       "id": "build:jenkins>test1"
    }, {
        "name": "test2",
        "id": "build:jenkins>test2"
    }, {
        "name": "maven",
        "id": "build:maven"
    }, {
        "name": "maven1",
        "id": "build:maven1"
    }]

"B": [{
        "name": "jenkins",
        "id": "build:jenkins"
    }, {
        "name": "m1",
        "id": "build:maven>m1"
    }, {
        "name": "m2",
        "id": "build:maven>m2"
    }, {
        "name": "maven3",
        "id": "build:maven3"
    }]

我试图得到一个结果数组“C”,它将根据“id”搜索两个数组中的可用子节点,并给出一个数组:

"C":
    [{  "id": "build:jenkins",
    "children": 
        [{"name": "test1","id": "build:jenkins>test1"},
        {"name": "test2","id": "build:jenkins>test2"}
    ]
},

{   "id": "build:maven",
    "children": 
        [{"name": "m1","id": "build:maven>m1"}, 
        {"name": "m2","id": "build:maven>m2"}
    ]
},

{"id": "build:maven1","children":[]}, 
{"id": "build:maven3","children":[]}
  ]

我试图遍历数组A,然后遍历数组B,根据id访问子节点,但不能同时在两个数组中进行双向搜索。请帮我得到数组C的结果。

2 个答案:

答案 0 :(得分:1)

首先,您需要一个实用程序函数,它将按id找到数组项:

function findArrayItemById(id, inArray) {
  var sep = '>'; // change this if you need another separator, can also be regex
  for (var i = 0; i < inArray.length; i++) {
    if (inArray[i].id === id.split(sep)[0])
      return inArray[i];
  }
  return false;
}

然后是一个函数,它以你需要的格式将多个数组合并为一个:

function buildMergedArray(arrays) {
  var result = [],
      sep = '>', // change this if you need another separator, can also be regex
      found;
  for (var i = 0; i < arrays.length; i++) {
    for (var j = 0; j < arrays[i].length; j++) {
      found = findArrayItemById(arrays[i][j].id, result);
      if (found)
        found.children.push(arrays[i][j]);
      else 
        result.push({
          id: arrays[i][j].id.split('>')[0],
          children: []
        });
    }
  }
  return result;
}

最后,您将获得所需的C结果,如下所示:

var result = buildMergedArray([source.A, source.B]);

答案 1 :(得分:0)

具有临时对象和新数组的递归构建的提议。

var object = { "A": [{ "name": "test1", "id": "build:jenkins>test1" }, { "name": "test2", "id": "build:jenkins>test2" }, { "name": "maven", "id": "build:maven" }, { "name": "maven1", "id": "build:maven1" }], "B": [{ "name": "jenkins", "id": "build:jenkins" }, { "name": "m1", "id": "build:maven>m1" }, { "name": "m2", "id": "build:maven>m2" }, { "name": "maven3", "id": "build:maven3" }], C: [] };

void function () {
    var temp = {}, PROP = ['id', 'name'];

    function split(s) {
        return s.split(':').pop().split('>');
    }

    function f(array) {
        array.forEach(function (a) {
            var o = temp;
            split(a.id).forEach(function (b) {
                o[b] = o[b] || {};
                o = o[b];
            });
            o.id = a.id;
            o.name = a.name;
        });

    }

    function r(object, array) {
        Object.keys(object).filter(function (a) { return !~PROP.indexOf(a); }).forEach(function (k) {
            var obj = {};
            PROP.forEach(function (a) {
                if (a in object[k]) {
                    obj[a] = object[k][a];
                }
            });
            obj.children = [];
            array.push(obj);
            if (typeof object[k] === 'object') {
                r(object[k], obj.children);
            }
        });
    }

    f(object.A);
    f(object.B);
    r(temp, object.C);
}();
document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');

另一种方法:

  

孩子们[]正在每个级别创建。是否有可能只在根级别,如问题中的数组C所示。还有可能有一个非递归的解决方案吗?

var object = { "A": [{ "name": "test1", "id": "build:jenkins>test1" }, { "name": "test2", "id": "build:jenkins>test2" }, { "name": "maven", "id": "build:maven" }, { "name": "maven1", "id": "build:maven1" }], "B": [{ "name": "jenkins", "id": "build:jenkins" }, { "name": "m1", "id": "build:maven>m1" }, { "name": "m2", "id": "build:maven>m2" }, { "name": "maven3", "id": "build:maven3" }], C: [] };
void function () {
    object.C = [];
    Object.keys(object).forEach(function (k) {
        object[k].forEach(function (a) {                    
            var path = a.id.split(/[:>]/);
            if (path.length === 2) {
                a = { id: a.id, children: [] };
                object.C.some(function (b) {
                    if (b.id === path.join(':')) {
                        return true;
                    }
                }) || object.C.push(a);
                return;
            }
            object.C.some(function (b) {
                a = JSON.parse(JSON.stringify(a));
                if (b.id === path.slice(0, 2).join(':')) {
                    b.children = b.children || [];
                    b.children.some(function (c, i, aa) {
                        if (c.id === a.id) {
                            aa[i] = a;
                            return true;
                        }
                    }) || b.children.push(a);
                    return true;
                }
            }) || object.C.push({ id: path.slice(0, 2).join(':'), children: [a] });
        });
    });
}();
document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');