Pregunta

First time using underscore and I am stuck and cannot find an example.

My data is:

[{
        "store_name": "Store 1",
        "franchisee_id": "id01",
        "dish_menu": "Breakfast",
        "dish_count": "17"
    }, {
        "store_name": "Store 1",
        "franchisee_id": "id01",
        "dish_menu": "Light Meals",
        "dish_count": "7"
    }, {
        "store_name": "Store 1",
        "franchisee_id": "id01",
        "dish_menu": "Sandwiches",
        "dish_count": "12"
    }, {
        "store_name": "Store 2",
        "franchisee_id": "id02",
        "dish_menu": "Breakfast",
        "dish_count": "7"
    },
        ............
]

I have managed (with some help from here) to pull the distinct store_name with the following chained command and then place it into a HTML statement I am building:

var stores = _.chain(json).pluck("store_name").sort().uniq(true).value();
var tempHTML = "";

stores.forEach(function (entry) {
    tempHTML = tempHTML + '<option value="' + entry + '">' + entry + '</option>';
});

But I am trying to match the franchisee_id to the distinct store_name and essentially build my HTML like below:

stores.forEach(function (entry) {
    tempHTML = tempHTML + '<option value="' + FRANCHISEE_ID + '">' + STORE_NAME + '</option>';
});

Is there a way to _.pluck a value for franchisee_id using the store_name value? There is a 1:1 relationship between these two fields so even getting the "first found" franchisee_id is fine. Thanks!

¿Fue útil?

Solución

You could do something like this to get your id/name pairs in the desired order:

var map_id_to_name = function(m, o) {
    m[o.franchisee_id] = o.store_name;
    return m;
};
var arrayify = function(name, id) {
    return [ name, id ];
};
var stores = _(data).chain()
                    .reduce(map_id_to_name, { })
                    .map(arrayify)
                    .sortBy(_.first)
                    .value();

Demo: http://jsfiddle.net/ambiguous/9xxS6/

That will give you an array of arrays in stores that you can spin through to build your <option>s; stores will look like this:

[
    [ "Store 1", "id01" ],
    [ "Store 2", "id02" ],
    ...
]

The store name will be in the first entry of the inner arrays and the franchise ID in the second. The whole thing will be sorted by store name. If you want a case insensitive sort then you can .sortBy(function(a) { return a[0].toLowerCase() }) instead.

The reduce(map_id_to_name, { }) collects the unique id/name pairs using an Object to automatically enforce uniqueness (the keys in an Object are unique after all). Then map(arrayify) converts the Object to an array-of-arrays so that you can sort things. You could use an array-of-objects instead, that would just be a small alteration to the map and sortBy calls.

Otros consejos

A different approach, extracting the desired information from the objects and then filtering the resulting array to get unique objects:

var stores = _(data).chain()

// convert each object to {store_name: ..., franchisee_id: ...}
.map(function(m) {
    return _.pick(m, "store_name", "franchisee_id");
})

//keep one of each
//can be shortened to .uniq(_.property('franchisee_id'))
.uniq(function(m) {
    return m.franchisee_id;
})

//sort by name
.sortBy("store_name")

//and get the array
.value();

Your final array would look like

[
    {store_name: "Store 1", franchisee_id: "id01"},
    {store_name: "Store 2", franchisee_id: "id02"}
]

And a demo to play with http://jsfiddle.net/mr82s/


And with a little _.mixin magic, you could further condense it to

_.mixin({
    properties: function() {
        var args = _.toArray(arguments);
        return function(obj) {
            return _.pick(obj, args);
        };
    }
});

var stores = _(data).chain()
.map(_.properties("store_name", "franchisee_id"))
.uniq(_.property('franchisee_id'))
.sortBy("store_name")
.value()

http://jsfiddle.net/nikoshr/mr82s/1/

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top