At underscore js, Can I get multiple columns with pluck method after input where method as linq select projection

后端 未结 7 1159
小蘑菇
小蘑菇 2021-01-30 12:59
var people = [
    {firstName : \"Thein\", city : \"ny\", qty : 5},
    {firstName : \"Michael\", city : \"ny\", qty : 3},
    {firstName : \"Bloom\", city : \"nj\", qty         


        
相关标签:
7条回答
  • 2021-01-30 13:45

    That one linear might save some lines:

    var results=_.pick(_.where(people, {city : "ny"}), 'firstName', 'qty');
    
    0 讨论(0)
  • 2021-01-30 13:48

    We don't have to use pluck, omit do the trick as well.

    var result = _.map(people, function(person) {
      return _.omit(person, 'city');
    });
    
    0 讨论(0)
  • 2021-01-30 13:49

    TL;DR Use :

    var results = _.chain(people)
        .where({ city: "ny" })
        .map(_.partialRight(_.pick, 'firstName', 'qty'))
        .value();
    

    But please read on for explanations as I feel the process of finding this solution is more interesting than the actual answer.


    The general pattern would be (it works with lodash too) :

    _.map(array, function(obj) { return _.pick(obj, 'x', 'y', 'z'); });

    Given this general map function which transforms each element of a collection, there are multiple ways to adapt this to your particular situation (that vouch for the flexibility of map, which is a very basic building block of functional programs).

    Let me present below several ways to implement our solution :

    var _ = require('lodash'); // @lodash 2.4.1 at the time of writing
    // use underscore if you want to, but please see http://stackoverflow.com/questions/13789618/differences-between-lodash-and-underscore
    
    
    /* la data */
    var people = [{
        firstName: "Thein",
        city: "ny",
        qty: 5
    }, {
        firstName: "Michael",
        city: "ny",
        qty: 3
    }, {
        firstName: "Bloom",
        city: "nj",
        qty: 10
    }];
    
    
    /* OPTION1 : mixin' with _ */
    _.mixin({
        pluckMany: function() {
            var array = arguments[0],
                propertiesToPluck = _.rest(arguments, 1);
    
            return _.map(array, function(item) {
    
                /* Alternative implementation 1.1
                 * ------------------------------
                 * Taken from @mMcGarnagle answer
                 * _each is easy to understand here,
                 * but has to modify the variable `obj` from a closure
                 * I try to avoid that for trivial cases like this one.
                 */
                var obj = {};
                _.each(propertiesToPluck, function(property) {
                    obj[property] = item[property];
                });
                return obj;
    
    
                /* Alternative implementation 1.2
                 * ------------------------------
                 * Rewrite the previous code,
                 * by passing the accumulator (previously`obj`, but really it is an object that accumulates the result being constructed) across function calls.
                 * This construction is typical of the `reduce` function, closer to a functionnal programming style.
                 */
                return _.reduce(propertiesToPluck, function(obj, property) {
                    obj[property] = item[property];
                    return obj;
                }, {});
    
    
                /* Alternative implementation 1.3
                 * ------------------------------
                 * If we are already using lodash/underscore,
                 * then let's use the `pick` function ! I also included an example of `flatten` here
                 */
                return _.pick(item, _.flatten(propertiesToPluck, true));
    
    
                /* Alternative implementation 1.4
                 * ------------------------------
                 * But really flatten is not needed.
                 */
                return _.partial(_.pick, item).apply(null, propertiesToPluck);
            });
        }
    });
    
    
    
    /* Let's use our mixed function !
     * Since we call several _ functions on the same object
     * it is more readable to chain the calls.
     */
    var results = _.chain(people)
        .where({
            city: "ny"
        })
        .pluckMany('firstName', 'qty')
        .value();
    
    
    
    /* OPTION 2 : without mixing our code with lodash/underscore */
    var results = _.chain(people)
        .where({
            city: "ny"
        })
        .map(_.partialRight(_.pick, 'firstName', 'qty'))
        .value();
    
    console.log(results);
    

    If you like this way of writing code with underscore or lodash, I highly suggest that you have a look at functional programming, as this style of writing as well as many functions (map, reduce amongst many others) come from there.

    Note : This is apparently a common question in underscore : https://github.com/jashkenas/underscore/issues/1104

    This is apparently no accident if these are left out of underscore/lodash : "composability is better than features". You could also say do one thing and do it well. This is also why _.mixin exists.

    0 讨论(0)
  • 2021-01-30 13:49

    My understanding is the author of the question wants to take an array of objects with many properties and strip each object down to a small list of properties.

    There are myriad ways of doing so with _ , but I like this way best. Pass in an empty result object which will be "this" inside the function. Iterate with _each , and _pick the fields you want:

    var myObjects = [
        { "first" : "eric",
          "last" : "gumbo",
          "code" : "x482"
        },
        { "first" : "john",
          "last" : "dinkman",
          "code" : "y9283"
        }
    ];
    
    var result = [];
    _.each( myObjects, function(itm) { this.push(_.pick(itm,"first","code")) }, result );
    
    console.log(result);
    
    0 讨论(0)
  • 2021-01-30 13:56

    To project to multiple properties, you need map, not pluck:

    var results = _.map(
        _.where(people, {city : "ny"}), 
        function(person) {
            return { firstName: person.firstName, qty: person.qty };
        }
    );
    

    [{"firstName":"Thein","qty":5},{"firstName":"Michael","qty":3}]

    (Fiddle)

    Note that, if you wanted to, you could create a helper method "pluckMany" that does the same thing as pluck with variable arguments:

    // first argument is the source array, followed by one or more property names
    var pluckMany = function() {
        // get the property names to pluck
        var source = arguments[0];
        var propertiesToPluck = _.rest(arguments, 1);
        return _.map(source, function(item) {
            var obj = {};
            _.each(propertiesToPluck, function(property) {
                obj[property] = item[property]; 
            });
            return obj;
        });
    };
    

    You can use the _.mixin function to add a "pluckMany" function to the _ namespace. Using this you can write simply:

    var results = _.chain(people).where({city : "ny"}).pluckMany( "firstName", "qty").value();
    

    (Fiddle)

    0 讨论(0)
  • 2021-01-30 13:57

    YAAUu-Yep Another Answer Using underscore...

    // use a proper browser to run this code snippet, a browser that is es6-compliant
    let people = [{
        firstName: "Thein",
        city: "ny",
        qty: 5
      },
      {
        firstName: "Michael",
        city: "ny",
        qty: 3
      },
      {
        firstName: "Bloom",
        city: "nj",
        qty: 10
      }
    ];
    // either you pick the properties you want 
    let picking = _.iteratee((person) => _(person).pick("firstName", "city"));
    // either you omit the properties you do not want
    let omitting = _.iteratee((person) => _(person).omit("qty"));
    // create the filter by city
    let living = (people, city) => _(people).where({
      "city": city
    });
    // put the "filter by city" into a mixin (as I assume it would be used again & again)
    _.mixin({
      living: living
    });
    // do the thing (twice), 
    // these chaining methods could be done into a mixin as well
    console.log("results by picking properties:", _(people).chain().living("ny").map(picking).value());
    console.log("results by omitting properties:", _(people).chain().living("ny").map(omitting).value());
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

    0 讨论(0)
提交回复
热议问题