webentwicklung-frage-antwort-db.com.de

Unterstrichene js: Kann ich nach der Eingabe mehrere Spalten mit der Zupfmethode erhalten, wobei die Methode als Linq-Projektion ausgewählt wird

var people = [
    {firstName : "Thein", city : "ny", qty : 5},
    {firstName : "Michael", city : "ny", qty : 3},
    {firstName : "Bloom", city : "nj", qty : 10}
];

var results=_.pluck(_.where(people, {city : "ny"}), 'firstName');

Zum Beispiel: Ich brauche firstName und qty.

40
ttacompu

Um auf mehrere Eigenschaften projizieren zu können, benötigen Sie map , nicht zupfen:

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

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

(Geige)

Wenn Sie möchten, können Sie eine Hilfsmethode "pluckMany" erstellen, die dasselbe tut wie das Zupfen mit Variablenargumenten:

// 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;
    });
};

Mit der Funktion _.mixin können Sie dem _-Namespace eine Funktion "pluckMany" hinzufügen. Mit diesem können Sie einfach schreiben:

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

(Geige)

62
McGarnagle

TL; DR Verwendung:

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

Aber bitte lesen Sie weiter für Erklärungen, da ich der Meinung bin, dass der Prozess, diese Lösung zu finden, interessanter ist als die eigentliche Antwort.


Das allgemeine Muster wäre (es funktioniert auch mit lodash ):

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

Angesichts dieser allgemeinen map - Funktion, die jedes Element einer Sammlung transformiert, gibt es mehrere Möglichkeiten, dies an Ihre spezielle Situation anzupassen (die für die Flexibilität von map bürgen). Dies ist ein sehr grundlegender Baustein für Funktionsprogramme.

Lassen Sie mich im Folgenden einige Möglichkeiten zur Implementierung unserer Lösung vorstellen:

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

Wenn Sie diese Art, Code mit underscore oder lodash zu schreiben, mögen, empfehle ich Ihnen dringend, funktionale Programmierung als Schreibweise anzusehen auch viele Funktionen (map, reduce unter vielen anderen) kommen von dort.

Hinweis: Dies ist anscheinend eine häufige Frage im Unterstrich: https://github.com/jashkenas/underscore/issues/1104 =

Dies ist anscheinend kein Zufall, wenn diese nicht unterstrichen werden: "Zusammensetzbarkeit ist besser als Features". Sie könnten auch do one thing and do it well Sagen. Dies ist auch der Grund, warum _.mixin Existiert.

17
nha

Meines Wissens ist der Autor der Frage ein Array von Objekten mit vielen Eigenschaften und möchte jedes Objekt auf eine kleine Liste von Eigenschaften zerlegen.

Es gibt unzählige Möglichkeiten, dies mit _ zu tun, aber ich mag diesen Weg am besten. Übergeben Sie ein leeres Ergebnisobjekt, das in der Funktion "this" ist. Wiederholen Sie mit _each und _picken Sie die gewünschten Felder:

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);
4
eeejay

Ja, ich wünschte, pluck hätte die Option, ein Array zu übergeben, aber in der Zwischenzeit könnten Sie Folgendes tun:

const pluckFields = (arr, fields) => _.map(arr, item => _.pick(item, fields))
4
tldr

Diese lineare Linie könnte einige Zeilen speichern: 

var results=_.pick(_.where(people, {city : "ny"}), 'firstName', 'qty');
0
Nadeem

YAAUu - Yep Eine weitere Antwort mit Unterstrich ...

// 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
zobidafly