Search code examples
underscore.jstastypie

underscore.js - _.groupBy nested attribute


Tastypie returns an array, including nested resources as follows:

data = [

{"adult_price": "123", "child_price": "123", "currency": [{"abbrev": "USD", "id": "1", "name": "US Dollars", "resource_uri": "/api/v1/currency/1/", "symbol": "$"}], "day": [{"day_of_week": "TUE", "id": "2", "resource_uri": "/api/v1/days/2/"}], "description": "Please enter the tour description here", "id": "1", "important": "ex. Please contact us to negotiate a price if you want to book the Fiat for 1 person only.", "location": [{"id": "1", "name": "Dublin", "resource_uri": "/api/v1/location/1/"}], "name": "test dublin", "resource_uri": "/api/v1/tours/1/", "start_time": "23:03:51", "subtitle": "ex. These prices include... but not...", "teenager_student_price": "123", "under_6_price": "123"}, 

{"adult_price": "22", "child_price": "22", "currency": [{"abbrev": "USD", "id": "1", "name": "US Dollars", "resource_uri": "/api/v1/currency/1/", "symbol": "$"}], "day": [{"day_of_week": "WED", "id": "3", "resource_uri": "/api/v1/days/3/"}], "description": "Please enter the tour description here", "id": "2", "important": "ex. Please contact us to negotiate a price if you want to book the Fiat for 1 person only.", "location": [{"id": "2", "name": "Venice", "resource_uri": "/api/v1/location/2/"}], "name": "test Venice", "resource_uri": "/api/v1/tours/2/", "start_time": "23:09:01", "subtitle": "ex. These prices include... but not...", "teenager_student_price": "22", "under_6_price": "22"}, 

{"adult_price": "22", "child_price": "222", "currency": [{"abbrev": "USD", "id": "1", "name": "US Dollars", "resource_uri": "/api/v1/currency/1/", "symbol": "$"}], "day": [{"day_of_week": "MON", "id": "1", "resource_uri": "/api/v1/days/1/"}, {"day_of_week": "TUE", "id": "2", "resource_uri": "/api/v1/days/2/"}, {"day_of_week": "WED", "id": "3", "resource_uri": "/api/v1/days/3/"}], "description": "Please enter the tour description here", "id": "3", "important": "ex. Please contact us to negotiate a price if you want to book the Fiat for 1 person only.", "location": [{"id": "3", "name": "Rome", "resource_uri": "/api/v1/location/3/"}], "name": "test Rome", "resource_uri": "/api/v1/tours/3/", "start_time": "23:15:09", "subtitle": "ex. These prices include... but not...", "teenager_student_price": "22", "under_6_price": "222"}, 

{"adult_price": "22", "child_price": "222", "currency": [{"abbrev": "USD", "id": "1", "name": "US Dollars", "resource_uri": "/api/v1/currency/1/", "symbol": "$"}], "day": [{"day_of_week": "MON", "id": "1", "resource_uri": "/api/v1/days/1/"}, {"day_of_week": "WED", "id": "3", "resource_uri": "/api/v1/days/3/"}], "description": "Please enter the tour description here", "id": "4", "important": "ex. Please contact us to negotiate a price if you want to book the Fiat for 1 person only.", "location": [{"id": "3", "name": "Rome", "resource_uri": "/api/v1/location/3/"}], "name": "test Rome 2", "resource_uri": "/api/v1/tours/4/", "start_time": "01:01:11", "subtitle": "ex. These prices include... but not...", "teenager_student_price": "22", "under_6_price": "22"}, {"adult_price": "123", "child_price": "123", "currency": [{"abbrev": "USD", "id": "1", "name": "US Dollars", "resource_uri": "/api/v1/currency/1/", "symbol": "$"}], "day": [{"day_of_week": "TUE", "id": "2", "resource_uri": "/api/v1/days/2/"}, {"day_of_week": "THU", "id": "4", "resource_uri": "/api/v1/days/4/"}], "description": "Please enter the tour description here", "id": "5", "important": "ex. Please contact us to negotiate a price if you want to book the Fiat for 1 person only.", "location": [{"id": "2", "name": "Venice", "resource_uri": "/api/v1/location/2/"}], "name": "test Venice 2", "resource_uri": "/api/v1/tours/5/", "start_time": "01:03:27", "subtitle": "ex. These prices include... but not...", "teenager_student_price": "123", "under_6_price": "123"}

]

I would like to perform a .groupBy that groups by the location[0].names attribute, which should return an array of 3 arrays. Is this possible?

How can I perform the equivalent of:

_.groupBy(data, 'location[0].name']

Solution

  • The second argument for groupBy can be a function or a string:

    groupBy _.groupBy(list, iterator)

    Splits a collection into sets, grouped by the result of running each value through iterator. If iterator is a string instead of a function, groups by the property named by iterator on each of the values.

    You want to use the function form since you're not grouping on a simple top-level property:

    _(data).groupBy(function(o) {
        return o.location[0].name;
    });
    

    Or:

    _(data).groupBy(o => o.location[0].name)
    

    Demo: http://jsfiddle.net/ambiguous/YFKXC/