At underscore js, Can I get multiple columns with pluck method after input where method as linq select projection
1 2 3 4 5 6 7 | 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'); |
例如:我需要
要投影到多个属性,需要
1 2 3 4 5 6 | var results = _.map( _.where(people, {city :"ny"}), function(person) { return { firstName: person.firstName, qty: person.qty }; } ); |
[{"firstName":"Thein","qty":5},{"firstName":"Michael","qty":3}]
(小提琴)
请注意,如果需要,可以创建一个助手方法"pullmany",该方法与使用变量参数pull的方法相同:
1 2 3 4 5 6 7 8 9 10 11 12 13 | // 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; }); }; |
您可以使用
1 | var results = _.chain(people).where({city :"ny"}).pluckMany("firstName","qty").value(); |
(小提琴)
使用:
1 2 3 4 | var results = _.chain(people) .where({ city:"ny" }) .map(_.partialRight(_.pick, 'firstName', 'qty')) .value(); |
但请继续阅读解释,因为我觉得找到这个解决方案的过程比实际答案更有趣。
一般的模式是(它也适用于
考虑到转换集合中每个元素的通用
让我介绍以下几种实现解决方案的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 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); |
如果您喜欢使用
注意:这显然是下划线中的一个常见问题:https://github.com/jashkenas/underline/issues/1104
如果不使用下划线/lodash:"可组合性比特性更好",这显然不是意外。你也可以说
是的,我希望
1 | const pluckFields = (arr, fields) => _.map(arr, item => _.pick(item, fields)) |
我的理解是,这个问题的作者希望得到一个具有许多属性的对象数组,并将每个对象分为一个小的属性列表。
有无数种方法可以做到,但我最喜欢这种方法。传递一个空的结果对象,该对象将在函数内为"this"。与每个字段进行迭代,然后选择所需的字段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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); |
耀优用下划线回答了另一个问题…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | // 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()); |
1 | <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"> |
一条直线可能会节省一些线条:
1 | var results=_.pick(_.where(people, {city :"ny"}), 'firstName', 'qty'); |
我们不必用拔毛,也不用做这个把戏。
1 2 3 | var result = _.map(people, function(person) { return _.omit(person, 'city'); }); |