使用Javascript和Underscore.js转换数组对象

Transform array of objects using Javascript and Underscore.js

本文关键字:转换 数组 对象 js Underscore Javascript 使用      更新时间:2023-09-26

假设我有以下列表:

var products = [
    {"id": 6, "name": "product6", "category": "category2", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
    {"id": 5, "name": "product5", "category": "category2", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
    {"id": 7, "name": "product7", "category": "category1", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
    {"id": 1, "name": "product1", "category": "category1", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
    {"id": 3, "name": "product3", "category": "category2", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
    {"id": 8, "name": "product8", "category": "category1", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
    {"id": 2, "name": "product2", "category": "category3", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
    {"id": 4, "name": "product4", "category": "category1", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3}
] 

我该如何把它变成这样的东西使用javascript和"理想的下划线。js groupBy?(或者考虑到下面的表格布局,你知道如何在这里包括月份吗?)正如我看到的,下面嵌套了结构会让我"几乎"到达那里。

var hierarchicalList = [
    { 
        "id": -1, // something unique I guess?
        "name": "category1", 
        "1": 216, // aggregate number of sales per week for all children
        "2": 148, 
        "3": 256, 
        "4": 24, 
        "5": 184, 
        "6": 128, 
        "7": 12,
        "children": [
            {
                "id": 7, 
                "name": "product7", 
                "1": 54, 
                "2": 37, 
                "3": 64, 
                "4":6, 
                "5": 46, 
                "6": 32, 
                "7": 3
            }
            {
                "id": 1, 
                "name": "product1", 
                "1": 54, 
                "2": 37, 
                "3": 64, 
                "4":6, 
                "5": 46, 
                "6": 32, 
                "7": 3
            }
        ]
    }, 
    { 
        "id": -2, 
        "name": "category2",  
        "1": 162, 
        "2": 111, 
        ...
        "7": 9,
        "children": [
            // product6, 5, 3
        ]
    }
]

我将使用它对表中的产品类别进行"行分组",我希望将我的数据结构插入react grid组件(如Griddle)中总结一下,在我的例子中,我该如何:

  • 从下划线groupBy类别结果中获取每周每个类别的总销售额?
https://jsfiddle.net/zt62a3Lc/

好吧。这里有一个潜在的解决方案。它可能不使用_。groupBy,但在我看来,如果你强迫自己走那条路,你可能会在试图解决问题时被绑在背后。

var categoryGraft = {};
products.forEach(function (product) {
    var key = product.category;
    if (typeof categoryGraft[key] === 'undefined') {
        categoryGraft[key] = {
            "1": 0, "2": 0, "3": 0, "4": 0, "5": 0, "6": 0, "7": 0,
            "name": key,
            "children": []
        };
    }
    categoryGraft[key]["1"] += product["1"];
    categoryGraft[key]["2"] += product["2"];
    categoryGraft[key]["3"] += product["3"];
    categoryGraft[key]["4"] += product["4"];
    categoryGraft[key]["5"] += product["5"];
    categoryGraft[key]["6"] += product["6"];
    categoryGraft[key]["7"] += product["7"];
    // delete from original or clone...
    delete product.category;
    categoryGraft[key].children.push(product);
});
var hierarchicalList = [];
var key, category;
for (key in categoryGraft) {
    category = categoryGraft[key];
    hierarchicalList.push(category);
}

这是我使用_.chain()的解决方案

它不限于1 to 7,并且可以与任何数量的数字属性一起使用。此外,它是一个不改变任何变量的功能解决方案。

    var products = [
        {"id": 6, "name": "product6", "category": "category2", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
        {"id": 5, "name": "product5", "category": "category2", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
        {"id": 7, "name": "product7", "category": "category1", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
        {"id": 1, "name": "product1", "category": "category1", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
        {"id": 3, "name": "product3", "category": "category2", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
        {"id": 8, "name": "product8", "category": "category1", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
        {"id": 2, "name": "product2", "category": "category3", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3},
        {"id": 4, "name": "product4", "category": "category1", "1": 54, "2": 37, "3": 64, "4":6, "5": 46, "6": 32, "7": 3}
    ] 
    // null coalescing helper
    var coal = (a, b) => a != null ? a : b
    _.chain(products)
    // make an object: {category1: [...], category2: [...], ...}
    .groupBy(c => c.category)
    .mapObject((val, key) =>
        _.chain(val)
        .reduce(
            ((a, b) =>
                _.chain(_.chain(a).keys().union(_.keys(b)).value())
                .filter(k => !_(['name', 'id']).contains(k))
                .map(k =>
                    [k, !isNaN(parseInt(k)) ? coal(a[k], 0) + coal(b[k], 0) : coal(a[k], b[k])]
                )
                .concat([["children", _(a.children).concat(b)]])
                .object()
                .value()
            ), {children: []}
        )
        .value()
    )
    // convert the object into a list of pairs [["category1", {...}], ["category2", {...}], ...]
    .pairs()
    .map((d, i) => 
        // d is a pair: ["category1", {...}]
        _.extend(d[1], {name: d[0], id: (i+1) * -1}) // make the id
    )
    .value()