关于javascript:在下划线js,我可以在输入后使用pluck方法获取多个列,其中方法为linq select projection

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

例如:我需要firstNameqty


要投影到多个属性,需要map,而不是提取:

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

您可以使用_.mixin函数向_名称空间添加"pullmany"函数。使用这个你可以简单地写:

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

但请继续阅读解释,因为我觉得找到这个解决方案的过程比实际答案更有趣。

一般的模式是(它也适用于lodash):

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

考虑到转换集合中每个元素的通用map函数,有多种方法可以使其适应您的特定情况(保证map的灵活性,这是功能程序的一个非常基本的构建块)。

让我介绍以下几种实现解决方案的方法:

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

如果您喜欢使用underscorelodash编写代码的方式,我强烈建议您看看函数编程,因为这种风格的编写以及许多函数(mapreduce等)都来自于此。

注意:这显然是下划线中的一个常见问题:https://github.com/jashkenas/underline/issues/1104

如果不使用下划线/lodash:"可组合性比特性更好",这显然不是意外。你也可以说do one thing and do it well。这也是_.mixin存在的原因。


是的,我希望pluck可以选择传递一个数组,但与此同时,您可以这样做:

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