将对象转换为数组并将名称映射为键和子项

Convert object to array and map name as key and children

我有这个数据集

var items = {
    1: {
        id: 1,
        name: 'foo',
        date: {
            MMM  : 'february',
            yyyy : '2014',
            S    : '14th'
        }
    },
    2: {
        id: 2,
        name: 'bar',
        date: {
            MMM  : 'february',
            yyyy : '2014',
            S    : '7th'
        }
    },
    3: {
        id: 3,
        name: 'bazz',
        date: {
            MMM  : 'august',
            yyyy : '2015',
            S    : '21st'
        }
    },
    4: {
        id: 4,
        name: 'sup',
        date: {
            MMM  : 'may',
            yyyy : '2015',
            S    : '8th'
        }
    },
    5: {
        id: 6,
        name: 'awe',
        date: {
            MMM  : 'february',
            yyyy : '2014',
            S    : '1st'
        }
    }

};

然后我使用带有此自定义函数的 lodash 将它们分组:

_.groupByMulti = function(obj, values, context) {
    if (!values.length) {
        return obj;
    }
    var byFirst = _.chain(obj)
    .groupBy(values[0], context)
    .value();

    var rest = values.slice(1);

    for (var prop in byFirst) {
        if (prop) {
            byFirst[prop] = _.groupByMulti(byFirst[prop], rest, context);
        }
    }

    return byFirst;
}

因此 _.groupByMulti(items, ['date.yyyy', 'date.MMM', 'date.S']); 将重新运行 :

{
    "2014": {
        "february": {
            "14th": [
                {
                    "id": 1,
                    "name": "foo",
                    "date": {
                        "MMM": "february",
                        "yyyy": "2014",
                        "S": "14th"
                    }
                }
            ],
            "7th": [
                {
                    "id": 2,
                    "name": "bar",
                    "date": {
                        "MMM": "february",
                        "yyyy": "2014",
                        "S": "7th"
                    }
                }
            ],
            "1st": [
                {
                    "id": 6,
                    "name": "awe",
                    "date": {
                        "MMM": "february",
                        "yyyy": "2014",
                        "S": "1st"
                    }
                }
            ]
        }
    },
    "2015": {
        "august": {
            "21st": [
                {
                    "id": 3,
                    "name": "bazz",
                    "date": {
                        "MMM": "august",
                        "yyyy": "2015",
                        "S": "21st"
                    }
                }
            ]
        },
        "may": {
            "8th": [
                {
                    "id": 4,
                    "name": "sup",
                    "date": {
                        "MMM": "may",
                        "yyyy": "2015",
                        "S": "8th"
                    }
                }
            ]
        }
    }
}

现在我该如何扩展我的 lodash 函数,以便它将对象转换为数组,并像这样设置它们:

[
    {
       key: '2015',
       children: [
           {
              key: 'february',
              children: [...]
           }
       ]
    }
]

鉴于您目前拥有:

var out = _.groupByMulti(items, ['date.yyyy', 'date.MMM', 'date.S']);

哪个returns你一个对象。要将其包装到数组中,这可能会起作用:

_.map(_.keys(out), function(year){

    return {
        key: year,
        children: _.map(_.keys(out[year]),function(month){
            return {
                key: month,
                children: out[year][month]
            }
        })
    }
});

根据 @Tao P. R. 的回答,我能够像这样扩展 groupByMulti 函数:

_.groupByMulti = function(obj, values, context) {
    if (!values.length) {
        return obj;
    }
    var byFirst = _.chain(obj)
        .groupBy(values[0], context)
        .value();

    var rest = values.slice(1);

    for (var prop in byFirst) {
        if (prop) {
            byFirst[prop] = _.groupByMulti(byFirst[prop], rest, context);
        }
    }

    byFirst = _.map(_.keys(byFirst), function(propName) {
        return {
            name: propName,
            children: byFirst[propName]
        }
    });

    return byFirst;
}

return _;