【问题标题】:Arrange JSON Array to given Hierarchy group without Parent ID将 JSON 数组排列到没有父 ID 的给定层次结构组
【发布时间】:2021-01-22 08:40:58
【问题描述】:

我有一个键名数组(我们称之为'Labels')和另一个对象数组(我们称之为'Data')。我正在尝试使用 Labels 数组的层次结构将 Data 数组转换为 Parent Child 结构。这意味着,First Data 将按“Gender(父) 分组,然后是“Age(Gender 的子代) 然后是“ID(年龄的孩子)

//.... means it can be any number of items
var Labels = ["Gender", "Age", "ID", ....];
var Data = [{
"Age":"22",
"Gender":"Male",
"ID":"A111"
},
{
"Age":"22",
"Gender":"Male",
"ID":"A113"
},
{
"Age":"23",
"Gender":"Male",
"ID":"A109"
},
{
"Age":"23",
"Gender":"Male",
"ID":"A115"
},
{
"Age":"22",
"Gender":"Male",
"ID":"A105"
},
{
"Age":"21",
"Gender":"Male",
"ID":"A107"
},
{
"Age":"23",
"Gender":"Male",
"ID":"A103"
},
{
"Age":"21",
"Gender":"Male",
"ID":"A101"
},
{
"Age":"22",
"Gender":"Female",
"ID":"A114"
},
{
"Age":"23",
"Gender":"Female",
"ID":"A112"
},
{
"Age":"22",
"Gender":"Female",
"ID":"A108"
},
{
"Age":"21",
"Gender":"Female",
"ID":"A104"
},
{
"Age":"23",
"Gender":"Female",
"ID":"A106"
},
{
"Age":"22",
"Gender":"Female",
"ID":"A102"
},
{
"Age":"21",
"Gender":"Female",
"ID":"A110"
},
{
"Age":"22",
"Gender":"Male",
"ID":"A111"
},
{
"Age":"21",
"Gender":"Male",
"ID":"A113"
},
{
"Age":"23",
"Gender":"Male",
"ID":"A109"
},
{
"Age":"23",
"Gender":"Male",
"ID":"A115"
},
{
"Age":"22",
"Gender":"Male",
"ID":"A105"
},
{
"Age":"21",
"Gender":"Male",
"ID":"A107"
},
{
"Age":"23",
"Gender":"Male",
"ID":"A103"
},
{
"Age":"21",
"Gender":"Male",
"ID":"A101"
},
{
"Age":"22",
"Gender":"Female",
"ID":"A114"
},
{
"Age":"23",
"Gender":"Female",
"ID":"A112"
},
{
"Age":"22",
"Gender":"Female",
"ID":"A108"
},
{
"Age":"21",
"Gender":"Female",
"ID":"A104"
},
{
"Age":"23",
"Gender":"Female",
"ID":"A106"
},
{
"Age":"22",
"Gender":"Female",
"ID":"A102"
},
{
"Age":"21",
"Gender":"Female",
"ID":"A110"
},
{
"Age":"22",
"Gender":"Male",
"ID":"A111"
},
{
"Age":"21",
"Gender":"Male",
"ID":"A113"
},
{
"Age":"23",
"Gender":"Male",
"ID":"A109"
},
{
"Age":"23",
"Gender":"Male",
"ID":"A115"
},
{
"Age":"22",
"Gender":"Male",
"ID":"A105"
},
{
"Age":"21",
"Gender":"Male",
"ID":"A107"
},
{
"Age":"23",
"Gender":"Male",
"ID":"A103"
},
{
"Age":"21",
"Gender":"Male",
"ID":"A101"
},
{
"Age":"22",
"Gender":"Female",
"ID":"A114"
},
{
"Age":"23",
"Gender":"Female",
"ID":"A112"
},
{
"Age":"22",
"Gender":"Female",
"ID":"A108"
},
{
"Age":"21",
"Gender":"Female",
"ID":"A104"
},
{
"Age":"23",
"Gender":"Female",
"ID":"A106"
},
{
"Age":"22",
"Gender":"Female",
"ID":"A102"
},
{
"Age":"21",
"Gender":"Female",
"ID":"A110"
}]

上述数据的预期输出应为:

var output = [{
            name: "Male",
            childrens:[
            {
                name: "21",
                childrens: [{name: "Al01"},{name: "Al07"}, ....]
            },
            {
                name: "22",
                childrens: [{name: "A111"},{name: "A113"}, ....]
            },
            {
                name: "23",
                childrens: [{name: "A109"},{name: "A115"}, ....]
            }
            ]
        },
        {
            name: "Female",
            childrens:[
            {
                name: "21",
                childrens: [{name: "Al04"},{name: "Al10"}, ....]
            },
            {
                name: "22",
                childrens: [{name: "A102"},{name: "A114"}, ....]
            },
            {
                name: "23",
                childrens: [{name: "A106"},{name: "A109"}, ....]
            }
            ]
        }];

我已经尝试groupBy() 如下所示但没有得到预期的输出。

var groupBy = function (xs, key) {
        return xs.reduce(function (rv, x) {
            (rv[x[key]] = rv[x[key]] || []).push(x);
            return rv;
        }, {});
    };
function calcCats(ca, ss) {
        let K2 = groupBy(ca, ss);
        ca = [];
        Object.keys(K2).forEach(cc => {
            K2[cc].forEach(kk=>{
                delete kk[ss];
            });
            let tv = { name: cc, type: ss };
            if(Object.keys(K2[cc][0]).length > 0)
            {
                tv.categories= K2[cc];
            }
            ca.push(tv);
        });
        return ca;
    }
    var output = [];
    Labels.forEach((ss, i) => {
        if (output.length <= 0) {
            let K1 = groupBy(output, ss);
            Object.keys(K1).forEach(cc => {
                output.push({ name: cc, categories: K1[cc] });
            });
        } else {
            output.forEach(ca => {
                ca.categories = calcCats(ca.categories, ss);
            });
        }
    });

【问题讨论】:

    标签: javascript jquery arrays


    【解决方案1】:

    您可以获取一个对象,该对象保留对实际关卡的组的引用,以及嵌套样式的关卡结果数组,并从键数组中获取新关卡。

    让我们看一下对象(_ 其余属性切换)

    {
        "Male": {
            "21": {
                "_": /**ref:1a**/
            },
            "22": {
                "_": /**ref:6**/
            },
            "23": {
                "_": /**ref:f**/
            },
            "_": /**ref:4**/
        },
        "Female": {
            "21": {
                "_": /**ref:39**/
            },
            "22": {
                "_": /**ref:26**/
            },
            "23": {
                "_": /**ref:31**/
            },
            "_": /**ref:24**/
        },
        "_": [
            {
                "name": "Male",
                "children": [
                    /**id:4**/
                    {
                        "name": "22",
                        "children": [
                            /**id:6**/
                            { "ID": "A111" },
                            { "ID": "A113" },
                            // ...
                        ]
                    },
                    {
                        "name": "23",
                        "children": [
                            /**id:f**/
                            { "ID": "A109" },
                            { "ID": "A115" },
                            // ...
                        ]
                    },
                    {
                        "name": "21",
                        "children": [
                            /**id:1a**/
                            { "ID": "A107" },
                            { "ID": "A101" },
                            // ...
                        ]
                    }
                ]
            },
            {
                "name": "Female",
                "children": [
                    /**id:24**/
                    {
                        "name": "22",
                        "children": [
                            /**id:26**/
                            { "ID": "A114" },
                            { "ID": "A108" },
                            // ...
                        ]
                    },
                    {
                        "name": "23",
                        "children": [
                            /**id:31**/
                            { "ID": "A112" },
                            { "ID": "A106" },
                            // ...
                        ]
                    },
                    {
                        "name": "21",
                        "children": [
                            /**id:39**/
                            { "ID": "A104" },
                            { "ID": "A110" },
                            // ...
                        ]
                    }
                ]
            }
        ]
    }
    

    该对象包含嵌套组的第一级 GenderMale/Female 和另一级 Age 及其值和对数组的引用。

    这不是结果想要的结构。

    结果包含具有name 属性的对象数组,该属性反映了级别值,随后是一个没有分组属性的对象。

    深入:

    外部reduce 迭代给定对象。以及它为每次迭代保留对象,这允许使用对象快速访问嵌套组。

    内部reduce获取一个关卡和该关卡的键,并从对象中解构键以获取没有实际关卡的键的对象。

    如果该级别没有具有实际组值的属性,则使用数组作为值创建具有名称的新属性和仅具有一个属性_ 的对象。该数组包含级别的所有值。需要下划线以防止与分组值的其他值发生冲突。

    实际上只有第一个结构是创建者,现在它不会出现在结果集中。为了在结果集中有这个数组,它需要添加一个引用该数组的对象作为子对象。

    最终返回具有关卡组的对象。

    在叶子中,数据对象的其余部分必须推送到数组中。

    const
        data = [{ Age: "22", Gender: "Male", ID: "A111" }, { Age: "22", Gender: "Male", ID: "A113" }, { Age: "23", Gender: "Male", ID: "A109" }, { Age: "23", Gender: "Male", ID: "A115" }, { Age: "22", Gender: "Male", ID: "A105" }, { Age: "21", Gender: "Male", ID: "A107" }, { Age: "23", Gender: "Male", ID: "A103" }, { Age: "21", Gender: "Male", ID: "A101" }, { Age: "22", Gender: "Female", ID: "A114" }, { Age: "23", Gender: "Female", ID: "A112" }, { Age: "22", Gender: "Female", ID: "A108" }, { Age: "21", Gender: "Female", ID: "A104" }, { Age: "23", Gender: "Female", ID: "A106" }, { Age: "22", Gender: "Female", ID: "A102" }, { Age: "21", Gender: "Female", ID: "A110" }, { Age: "22", Gender: "Male", ID: "A111" }, { Age: "21", Gender: "Male", ID: "A113" }, { Age: "23", Gender: "Male", ID: "A109" }, { Age: "23", Gender: "Male", ID: "A115" }, { Age: "22", Gender: "Male", ID: "A105" }, { Age: "21", Gender: "Male", ID: "A107" }, { Age: "23", Gender: "Male", ID: "A103" }, { Age: "21", Gender: "Male", ID: "A101" }, { Age: "22", Gender: "Female", ID: "A114" }, { Age: "23", Gender: "Female", ID: "A112" }, { Age: "22", Gender: "Female", ID: "A108" }, { Age: "21", Gender: "Female", ID: "A104" }, { Age: "23", Gender: "Female", ID: "A106" }, { Age: "22", Gender: "Female", ID: "A102" }, { Age: "21", Gender: "Female", ID: "A110" }, { Age: "22", Gender: "Male", ID: "A111" }, { Age: "21", Gender: "Male", ID: "A113" }, { Age: "23", Gender: "Male", ID: "A109" }, { Age: "23", Gender: "Male", ID: "A115" }, { Age: "22", Gender: "Male", ID: "A105" }, { Age: "21", Gender: "Male", ID: "A107" }, { Age: "23", Gender: "Male", ID: "A103" }, { Age: "21", Gender: "Male", ID: "A101" }, { Age: "22", Gender: "Female", ID: "A114" }, { Age: "23", Gender: "Female", ID: "A112" }, { Age: "22", Gender: "Female", ID: "A108" }, { Age: "21", Gender: "Female", ID: "A104" }, { Age: "23", Gender: "Female", ID: "A106" }, { Age: "22", Gender: "Female", ID: "A102" }, { Age: "21", Gender: "Female", ID: "A110" }],
        keys = ['Gender', 'Age'],
        tree = data
            .reduce((r, o) => {
                keys
                    .reduce((level, key) => {
                        let name;
                        ({ [key]: name, ...o } = o);
    
                        if (!level[name]) {
                            level[name] = { _: [] };
                            level._.push({ name, children: level[name]._ });
                        }
                        return level[name];
                    }, r)
                    ._
                    .push(o);
                return r;
            }, { _: [] })
            ._;
    
    console.log(tree);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      猜你喜欢
      • 2011-05-12
      • 1970-01-01
      • 2018-04-13
      • 2018-10-18
      • 1970-01-01
      • 2015-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多