问题 平面阵列到多维数组(JavaScript)


我有以下数组:

var sampleArray = [
  "CONTAINER",
  "BODY",
  "NEWS",
  "TITLE"];

我想要以下输出:

var desiredOutput = [{
        "CONTAINER": [{
            "BODY": [{
                "NEWS": [{
                    "TITLE": []
                }]
            }]
        }]
    }];

我怎样才能在JavaScript中实现这一目标?

已经尝试过递归循环,但它不起作用,给我未定义。

    dataChange(sampleArray);
    function dataChange(data) {
        for (var i = 0; i < data.length; i++) {
            changeTheArray[data[i]] = data[i + 1];
            data.splice(i, 1);
            dataChange(changeTheArray[data[i]]);
        }
    }

谢谢


7795
2017-10-26 09:16


起源



答案:


这样做:

const sampleArray = ["CONTAINER", "BODY", "NEWS", "TITLE"];
const data = [];    // Starting element.
let current = data; // Pointer to the current element in the loop

sampleArray.forEach(key => {     // For every entry, named `key` in `sampleArray`,
    const next = [];             // New array
    current.push({[key]: next}); // Add `{key: []}` to the current array,
    current = next;              // Move the pointer to the array we just added.
});

console.log(data);

{[key]: next} 是相对较新的语法。他们是 计算属性名称

这个:

const a = 'foo';
const b = {[a]: 'bar'};

类似于:

const a = 'foo';
const b = {};
b[a] = 'bar';

可以 重写了 forEach 作为单线:

const sampleArray = ["CONTAINER", "BODY", "NEWS", "TITLE"];
const data = [];    // Starting element.
let current = data; // Pointer to the current element in the loop

sampleArray.forEach(key => current.push({[key]: current = [] }));

console.log(data);

这个 current.push 有点反直觉地工作:

  1. 构造一个要推送的新元素。这会为其分配一个新值 current
  2. 将新元素推送到 参考  .push 被召唤。
    • 那个参考是值的 current  之前  current = []

3
2017-10-26 09:24



问题问题是变幻无常的野兽;-) - Alnitak
我会去一个额外的临时变量来避免函数的第二行中的取消引用: let next = []; current.push({[key] : next}); current = next - Alnitak
@Alnitak:是的,我有点惊讶。好建议:-) - Cerbrus
Re:你的编辑 - 为什么滥用 .forEach 对它的使用顺序知之甚少 current 变量何时 .reduce 是专门为处理这种积累而设计的?我曾考虑过类似的解决方案,但没有参考语言规范,我无法确定是否转让 current = [] 发生在之前或之后 .push。 - Alnitak
@Alnitak:你打电话的那一刻 .push。该 this 变量 .push 设置为旧值 current。该引用不会改变。我并不是说它是一段很好的代码。我刚刚意识到这是可能的,并希望添加它。 - Cerbrus


答案:


这样做:

const sampleArray = ["CONTAINER", "BODY", "NEWS", "TITLE"];
const data = [];    // Starting element.
let current = data; // Pointer to the current element in the loop

sampleArray.forEach(key => {     // For every entry, named `key` in `sampleArray`,
    const next = [];             // New array
    current.push({[key]: next}); // Add `{key: []}` to the current array,
    current = next;              // Move the pointer to the array we just added.
});

console.log(data);

{[key]: next} 是相对较新的语法。他们是 计算属性名称

这个:

const a = 'foo';
const b = {[a]: 'bar'};

类似于:

const a = 'foo';
const b = {};
b[a] = 'bar';

可以 重写了 forEach 作为单线:

const sampleArray = ["CONTAINER", "BODY", "NEWS", "TITLE"];
const data = [];    // Starting element.
let current = data; // Pointer to the current element in the loop

sampleArray.forEach(key => current.push({[key]: current = [] }));

console.log(data);

这个 current.push 有点反直觉地工作:

  1. 构造一个要推送的新元素。这会为其分配一个新值 current
  2. 将新元素推送到 参考  .push 被召唤。
    • 那个参考是值的 current  之前  current = []

3
2017-10-26 09:24



问题问题是变幻无常的野兽;-) - Alnitak
我会去一个额外的临时变量来避免函数的第二行中的取消引用: let next = []; current.push({[key] : next}); current = next - Alnitak
@Alnitak:是的,我有点惊讶。好建议:-) - Cerbrus
Re:你的编辑 - 为什么滥用 .forEach 对它的使用顺序知之甚少 current 变量何时 .reduce 是专门为处理这种积累而设计的?我曾考虑过类似的解决方案,但没有参考语言规范,我无法确定是否转让 current = [] 发生在之前或之后 .push。 - Alnitak
@Alnitak:你打电话的那一刻 .push。该 this 变量 .push 设置为旧值 current。该引用不会改变。我并不是说它是一段很好的代码。我刚刚意识到这是可能的,并希望添加它。 - Cerbrus


这就是你要求的,在一行中,没有其他变量:

let desiredOutput = sampleArray.reduceRight((obj, key) => [ { [key]: obj } ], []);

reduceRight 呼叫, 从数组的右端开始,逐步累积当前数据(以初始值为种子) [])作为新对象中单个键的值 { [key] : _value_ } 其中该对象本身是数组中的单个条目 [ ... ]


9
2017-10-26 09:24



好巫术......我试着建立一个 reduce 方法,但由于累加器向下移动树而无法使其工作...... reverse 是一个聪明的触摸:D - Cerbrus
@Xufox是的,我在你评论时我自己也得出了这个结论 - 我的原始测试因为这个事实而感到困惑 .reverse() 做了 到位 逆转,我的测试数据已经损坏。所以使用 .reduceRight 实际上更好,因为它保持原始数组不变。 - Alnitak
@Cerbrus其实, reduceRight() 更好。 - Alnitak
@Cerbrus我也试过了 reduce 并建立在类似的价值上 {data: [], referenceToInnerArray: []},但Alnitak很快完成了...... - Xufox
更好的是:D我不知道有这样的事情 reduceRight... - Cerbrus


嗨,我做了一点 演示 :

var sampleArray = [
      "CONTAINER",
      "BODY",
      "NEWS",
      "TITLE"
    ], 
    generateArray = [], 
    tmp = null;

for(var i = 0; i < sampleArray.length; i++) {
  if(tmp===null){
    generateArray[sampleArray[i]] = {};
    tmp = generateArray[sampleArray[i]];
  }else{
    tmp[sampleArray[i]] = {};
    tmp = tmp[sampleArray[i]];
  }         
}

console.log(generateArray);

1
2017-10-26 09:23