Underscore.js:将对象数组转换为多级嵌套对象?

时间:2012-12-26 19:19:34

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

您如何使用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'
        }
    }
}

1 个答案:

答案 0 :(得分:2)

有一个很好的函数叫groupBy,它可以完全满足您的需求,但仅适用于一维对象。在this answer中,我编写了一个通用的多维版本,但对于您的情况,以下功能脚本就足够了:

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"]);