简体   繁体   English

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

[英]Transform array of objects using Javascript and Underscore.js

Assuming I have the following list: 假设我有以下列表:

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}
] 

How would I then turn it into something like this using javascript and "ideally underscore.js groupBy? (or considering the table layout below, have you got any idea how to include the months here also?). As I see it the below nested structure would get me "almost" there. 然后,如何使用javascript和“理想情况下underscore.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
        ]
    }
]

I'm going to use this for "row grouping" on product category in a table, where I'm looking to plug my datastructure in a react grid component like Griddle So to summarize, in my case how would I: 我将使用它在表中的产品类别上进行“行分组”,在这里我希望将我的数据结构插入到诸如Griddle这样的React网格组件中。因此,在我的情况下,我将如何总结:

  • get the aggregated sales per category per week from the underscore groupBy category result? 从下划线分组中按类别获得每周每个类别的汇总销售?

https://jsfiddle.net/zt62a3Lc/ https://jsfiddle.net/zt62a3Lc/

Well. 好。 Here's a potential solution. 这是一个潜在的解决方案。 It might not use _.groupBy, but IMO if you forced yourself down that path you might be trying to solve the problem with hands tied behind your back. 它可能不使用_.groupBy,但是IMO如果您强迫自己沿着那条路走,您可能会双手交叉绑住以解决问题。

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);
}

Here's my solution using _.chain() 这是我使用_.chain()解决方案

It's not restricted to 1 to 7 and works with any number of numeric properties. 它不限于1 to 7并且可以使用任意数量的数字属性。 Moreover it is a functional solution without mutating any variable. 此外,它是一种功能解决方案,无需更改任何变量。

    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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM