【问题标题】:Underscore.js: transform an array of objects into a multi-level nested object?Underscore.js:将对象数组转换为多级嵌套对象?
【发布时间】:2012-12-12 06:44:07
【问题描述】:

您将如何使用 underscore.js 以函数式的方式进行这种转换?我最近多次重复以下模式,对我来说似乎有点难看。

var fruitList = [
        { id:1, name:lime, color:green, size:small },
        { id:2, name:banana, color:yellow, size:large },
        { id:3, name:lemon, color:yellow, size:small },
        { id:4, name:papaya, color:green, size:large },
        { id:5, name:kiwi, color:green, size:small },
        { id:6, name:apple, color:green, size:small },
        { id:7, name:pear, color:yellow, size:small },
        { id:8, name:grape, color:green, size:small },
        { id:9, name:mango, color:yellow, size:large },
        { id:10, name:honeydew, color:green, size:large }
    ],
    fruitByColorThenSize = {};

jQuery.each(fruitList, function (fruit) {
    if (!fruitByColorThenSize[fruit.color]) {
        fruitByColorThenSize[fruit.color] = {};
    }

    if (!fruitByColorThenSize[fruit.color][fruit.size]) {
        fruitByColorThenSize[fruit.color][fruit.size] = {};
    }

    fruitByColorThenSize[fruit.color][fruit.size][fruit.id] = fruit.name;
});

fruitByColorThenSize 看起来类似于:

{
    yellow: {
        large: {
            2: 'banana',
            9: 'mango'
        },
        small: {
            3: 'lemon',
            7: 'pear'
        }
    },
    green: {
        large: {
            4: 'papaya',
            10: 'honeydew'
        },
        small: {
            1: 'lime',
            5: 'kiwi',
            6: 'apple',
            8: 'grape'
        }
    }
}

【问题讨论】:

    标签: javascript arrays functional-programming underscore.js transformation


    【解决方案1】:

    有一个名为groupBy 的好函数,它完全符合您的要求,但仅适用于一维对象。在this answer 中,我编写了它的通用多维版本,但对于您的情况,以下 functional 脚本就足够了:

    var fruitList = […];
    
    var fruitByColorThenSize = _.groupBy(fruitList, "color");
    for (var color in fruitByColorThenSize) {
        var byColor = _.groupBy(fruitByColorThenSize[color], "size");
        for (var size in byColor) {
            var bySize = _.groupBy(byColor[size], "id");
            for (var id in bySize) {
                bySize[id] = bySize[0].name;
            }
            byColor[size] = bySize;
        }
        fruitByColorThenSize[color] = byColor;
    }
    

    我最近多次重复以下模式

    然后写一个泛型函数抽象它!很简单:

    function getBy(arr, valprop, props) {
        var res = {};
        $.each(arr, function(obj) {
            var acc = res;
            for (var i=0; i<props.length; i++) {
                var prop = obj[props[i]];
                if (i==props.length-1) 
                    acc[prop] = obj[valprop];
                else {
                    if (! (prop in acc))
                        acc[prop] = {};
                    acc = acc[prop];
                }
            }
        });
        return res;
    }
    // usage:
    var fruitByColorThenSize = getBy(fruitList, "name", ["color", "size", "id"]);
    

    【讨论】:

    • 我得到一个数组using your solution,而不是一个对象。
    • 是的,这就是其中的一部分。 @Bergi 的代码生成对象数组的数组,而我正在寻找对象对象的对象。明天我将更仔细地检查链接的多维答案。此外,underscore.nest 的链接看起来很酷。谢谢!
    • @idbehold:哎呀,我虽然 Underscore 的对象映射会返回一个对象。这将使答案变得不那么实用:-(
    猜你喜欢
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 2015-03-26
    • 2019-01-31
    相关资源
    最近更新 更多