JS: Reduce array to nested objects

后端 未结 2 1592
你的背包
你的背包 2021-01-21 23:46

So I have this array

var mapped = [[2016, \"October\", \"Monday\", {object}], [2017, \"January\", \"Friday\", {object}], [2017, \"January\", \"Wednesday\", {obje         


        
相关标签:
2条回答
  • 2021-01-22 00:20

    Not exactly what you specified, but I feel the following script outputs a format that will be most useful -- it only produces arrays at the deepest level:

    const  mapped = [[2016, "October", "Monday", { a: 1 }], [2017, "January", "Friday", { a: 1 }], [2017, "January", "Wednesday", { a: 1 }], [2017, "October", "Monday", { a: 1 }]];
       
    const result = mapped.reduce( (acc, [year, month, day, object]) => {
        let curr = acc[year] = acc[year] || {};
        curr = curr[month] = curr[month] || {};
        curr = curr[day] = curr[day] || [];
        curr.push(object);
        return acc;
    }, {});
    
    console.log(result);
       
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    With array wrapping

    If you really need the wrapping arrays, you can apply an extra recursive function to the previous result:

    const  mapped = [[2016, "October", "Monday", { a: 1 }], [2017, "January", "Friday", { a: 1 }], [2017, "January", "Wednesday", { a: 1 }], [2017, "October", "Monday", { a: 1 }]];
       
    const result = mapped.reduce( (acc, [year, month, day, object]) => {
        let curr = acc[year] = acc[year] || {};
        curr = curr[month] = curr[month] || {};
        curr = curr[day] = curr[day] || [];
        curr.push(object);
        return acc;
    }, {});
    
    function wrapInArrays(data) {
        return Array.isArray(data) ? data 
            : Object.entries(data).map ( ([key, value]) => {
                return { [key]: wrapInArrays(value) };
            });
    }
    
    const wrapped = wrapInArrays(result);
    console.log(wrapped);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    0 讨论(0)
  • 2021-01-22 00:26

    To achieve the same exact structure you can try the strategy below. This will work upto any level of nesting and will continue to build the nested object. Please have a look at the example to see various levels of nesting which will be handled generically.

    • Map each element into the corresponding nested structure (Map with reduce)

    • Combine each element from mapped array into a single object to merge all redundant keys

    • Convert the final nested object into the desired array structure.

    const mapped = [[2016, "October", "Monday", "Morning", {time: "10AM"}], [2017, "January", "Friday", {object: "OBJECT"}], [2017, "January", "Wednesday", {object: "OBJECT"}], [2017, "October", "Monday", {object: "OBJECT"}]];
    
    // Map all objects to the respective nested structure
    const nestedMap = mapped.map(elem => {
      let reversed = [...elem.reverse()];
      let firstElem = reversed.splice(0, 1)[0];
      return reversed.reduce((acc, elem) => {let newAcc = {}; newAcc[elem] = [acc]; return {...newAcc}}, firstElem);
    })
    
    // Combine array to form a single object
    const nestedObj = nestedMap.reduce((acc, elem) => {
      let firstKey = Object.keys(elem)[0];
      acc[firstKey]
        ?
        acc[firstKey].push(elem[firstKey][0])
        :
        acc[firstKey] = elem[firstKey];
      return acc;
    }, {})
    
    // Convert back into the array with each object as element
    const nestedFinalArr = Object.keys(nestedObj).map(key => ({[key]: nestedObj[key]}))
    
    console.log(nestedFinalArr);

    0 讨论(0)
提交回复
热议问题