I'm trying to sort a JSON into multiple arrays based on type, my current json is:

// current json file:
{
    "res": [
        {
            "type" : "stream",
            "price" : "3.99",
            "id" : "13nee"
        },
        {
            "type" : "stream",
            "price" : "2.99",
            "id" : "8ejwj"
        },
        {
            "type" : "buy",
            "price" : "3.99".
            "id" : "9akwk"
        },      
        ...
    ]
}

I'm looking to sort it into multiple arrays by type like below:

var sorted = {
    "stream" : [
        {
            "price" : "2.99",
            "id" : "8ejwj"
        },
        {
            "price" : ".99",
            "id" : "13nee"
        },

        ... // other objects with type: "stream"
    ],
    "buy" : [
        {
            "price" : "3.99".
            "id" : "9akwk"
        },
        ... // other objects with type: "buy"
    ]
}

I've tried it, but the only solution I can think of is by cases - run if loop, if case matches type, then push object to array. Is there a more elegant solution?

有帮助吗?

解决方案

var items = {};
var i = 0;

for(i; i < res.length; i += 1){
    var resItem = res[i];
    if(items.hasOwnProperty(resItem.type)){
       items[resItem.type].push({price:resItem.price, id:resItem.id});
    } else {
        items[resItem.type] = [{price:resItem.price, id:resItem.id}];
    }
}

The properties on JavaScript objects are hashed, so you can dynamically match and generate new objects like above. If you want to apply a well ordering sort, you'll need to apply it to the arrays of the newly generated items object.

其他提示

Step 1 : Convert the JSON to a jquery object :

var x = jQuery.parseJSON( jsonString );

Step 2: Use underscore library's _.groupBy to group :

_.groupBy(x,'type');

There might be some adjustment you need to do for x being array or object.

Edit : You don't need step1. Just do :

sorted = _.groupBy(json.res,'type');

You could do something like this with ECMA5. This performs, generically, the sort and reduce that you have indicated in your question, so you can add more fields to your data without having to change the routine. It also leaves your original data intact.

Javascript

var original = {
    'res': [{
            'type': 'stream',
            'price': '3.99',
             'id': '13nee'
        }, {
            'type': 'stream',
            'price': '2.99',
            'id': '8ejwj'
        }, {
            'type': 'buy',
            'price': '3.99',
            'id': '9akwk'
        }]
    },
    sorted = {};

original.res.slice().sort(function (a, b) {
    a = +(a.price);
    b = +(b.price);

    if (a < b) {
        return -1;
    }

    if (a > b) {
        return 1;
    }

    return 0;
}).reduce(function (acc, element) {
    if (!acc[element.type]) {
        acc[element.type] = [];
    }

    acc[element.type].push(Object.keys(element).filter(function (name) {
        return name !== 'type';
    }).reduce(function (prev, name) {
        prev[name] = element[name];

        return prev;
    }, {}));

    return acc;
}, sorted);

console.log(JSON.stringify(sorted));

Output

{
    "stream": [{
        "price": "2.99",
        "id": "8ejwj"
    }, {
        "price": "3.99",
        "id": "13nee"
    }],
    "buy": [{
        "price": "3.99",
        "id": "9akwk"
    }]
}

On jsFiddle

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top