将多维数组变成树状结构

时间:2018-08-03 12:04:09

标签: javascript arrays multidimensional-array

我有一个多维数组,如下所示:

[
    {"primary":{"sub":{"ID":[]}}},
    {"primary":{"sub":{"Name":[]}}},
    {"primary":{"ID":[]}},
    {"primary":{"Name":[]}}
]

我想获得唯一的属性并将其排序到具有以下结构的树中:

primary
   sub
      ID
      Name
   ID
   Name

我尝试了很多事情,最新的是:

function multiDimensionalUnique(arr) {
    var uniques = [];
    var itemsFound = {};
    for (var i = 0, l = arr.length; i < l; i++) {
      var stringified = JSON.stringify(arr[i]);
      if (itemsFound[stringified]) {
        continue;
      }
      uniques.push(arr[i]);
      itemsFound[stringified] = true;
    }
    return uniques;
}

uniqueCols = multiDimensionalUnique(arrayCols);

但这没用。

我还研究了分组功能和归约功能(我无法设法将其包裹住),但到目前为止尚未解决。

重要的是要注意,这些属性都是动态的,结构可能非常复杂,并且我不确切知道我将事先获得什么数据,只是上面的代码是这样(非常简化)

2 个答案:

答案 0 :(得分:4)

一个递归调用的函数dive()可以完成这项工作,请参见此处:

var inp=[{"primary":{"sub":{"ID":[1,2,3]}}},
    {"primary":{"sub":{"Name":[4,5,6]}}},
    {"primary":{"ID":[7,8,9]}},
    {"primary":{"Name":[5,5,5]}}];
var tree={};


function dive(tree,obj){
  for (var p in obj) {
    if (!tree[p]) tree[p]=obj[p];
    else     dive(tree[p],obj[p]);
  }
}

inp.forEach((el)=>dive(tree,el));

console.log(tree);

我随心所欲地精打细算带有一些内容的空数组。当然,它对空数组也能很好地工作。

结果:

{
  "primary": {
    "sub": {
      "ID": [
        1,
        2,
        3
      ],
      "Name": [
        4,
        5,
        6
      ]
    },
    "ID": [
      7,
      8,
      9
    ],
    "Name": [
      5,
      5,
      5
    ]
  }
}

答案 1 :(得分:0)

/* provided input */
const array= [
    {"primary":{"sub":{"ID":[]}}},
    {"primary":{"sub":{"Name":[]}}},
    {"primary":{"ID":[]}},
    {"primary":{"Name":[]}}
]
/* expected output 
    primary
   sub
      ID
      Name
   ID
   Name
*/

const recursivelyPushPropertyNames=  function (o, aggregated) {
  for (let p in o) {
    if ("object" === typeof o[p] && !Array.isArray(o[p])) {
        if (!(p in aggregated)) {
        aggregated[p]= []
      }
      recursivelyPushPropertyNames(o[p], aggregated[p])
    }

    if (0 > aggregated.indexOf(p)) {
      aggregated.push(p)
    }
  }

  console.log("Step 1.B: recursivelyPushPropertyNames(o, aggregated) "/* , aggregated */ )
}
const aggregate= function (arr) {
    const aggregated = []
  for (let i = 0, l = arr.length; i < l; i++) {
    recursivelyPushPropertyNames(arr[i], aggregated)            
  }
  console.log("Step 1.A: aggregate(arr) ", aggregated )
  return aggregated
}

const indent = function (str, tabcount) {
    let c=0, t="";
  while (c++ < tabcount) {
    t= t.concat('\t')
  }
  return t.concat(str)
}
const displayKeys= function (aggregatedList, tabcount) {
  let output= ""
  tabcount= tabcount || 0
    numeric: for (let i=0; i < aggregatedList.length; i++) {
    if ( aggregatedList[i] in aggregatedList ) {
        output= output.concat(
        indent(aggregatedList[i], tabcount),
        '\n',
        displayKeys(
            aggregatedList[ aggregatedList[i] ],
            1 + tabcount
        )
      )
    }
    else {
        output= output.concat(
        indent(aggregatedList[i], tabcount),
        '\n'
      )
    }
  }
  console.log("Step 2: displayKeys(aggregatedList, tabcount)\n", output)
  return output
}

// - All done done
console.log(
    displayKeys(
    aggregate(array)
  )
)