相当于_.pick()但对于Lo-dash中的数组

per*_*mon 32 javascript arrays lodash

我有以下集合:

var columns = [
    { key:'url', width:20, type:'text' },
    { key:'title', width:21, type:'text' },
    { key:'desc', width:22, type:'text' },
    { key:'domain', width:23, type:'text' },
    { key:'user', width:24, type:'text' }
];
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种方法来映射一个带有拾取键的对象数组,类似于:

_.mapPick(columns, [width]) 
// [{width:20},{width:21},{width:22},{width:23},{width:24}]
Run Code Online (Sandbox Code Playgroud)

我知道我可以像这样扩展lo-dash:

_.mixin({
    mapPick:  mapPick:function (objs,keys){
        return _.map(objs, function (obj) {
            return _.pick(obj,keys)
        })
    }

});
Run Code Online (Sandbox Code Playgroud)

我不确定是否有一些我缺少的本机功能.

我在这里发现了一个类似的问题,但我正在寻找一种更为低调的本土方式.

Ada*_*uch 25

我认为map() + pick()方法是你最好的选择.您可以编写回调而不是创建内联函数:

_.map(columns, _.partialRight(_.pick, 'key'));
Run Code Online (Sandbox Code Playgroud)

  • 你应该解释一下`partialRight`用于艰难的东西;) (22认同)

Vla*_*lad 20

在我的情况下我也需要强制转换类型,问题是TS编译器代表Adam Boduch解决方案返回一个布尔值,所以我找到一个简单的方法来做到这一点:

_.map(columns, item => { return { key: item.key } });
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您还可以添加一些新属性.

PS因为我无法发表评论,所以我将在这里添加有关partialRight用法的说明:

_.map(columns, _.partialRight(_.pick, 'key'));
Run Code Online (Sandbox Code Playgroud)

首先,如果你调用_.map(array, func) func将为每个数组元素调用.所以它是平等的:_.map(array, item => func(item)).

其次,调用partialRight的结果将是一个函数newFunc,因此我们可以将Adam的代码表示为:

var newFunc = _.partialRight(_.pick, 'key');
_.map(array, item => newFunc(item));
Run Code Online (Sandbox Code Playgroud)

第三,我们可以将newFunc逻辑表示为:

function newFunc(item) {
    return _.pick(item, 'key')
}
Run Code Online (Sandbox Code Playgroud)

最后,我认为对于这个问题最可理解和最易读的解决方案是:

_.map(columns, item => _.pick(item, 'key'))
Run Code Online (Sandbox Code Playgroud)

  • 注意箭头函数`=>`仅适用于ES6兼容的浏览器.对于Safari/IE支持,您可以使用旧的匿名函数:`_. map(columns,function(item){return _.pick(item,'key')}); (3认同)

Dav*_*vid 14

我发现,在简单的解决方案图的例子:

var users = [
    {name:'David',age:35},
    {name:'Kate',age:28},
];
_.map(users,'age'); // [35,28]
Run Code Online (Sandbox Code Playgroud)

  • 问题是,它应该返回 `[{age:35},{age:28}]` (4认同)

ale*_*ehr 8

使用 ES6解构箭头函数,你可以这样做:

columns.map(({width}) => ({width}))
Run Code Online (Sandbox Code Playgroud)

不需要 lodash。


Jac*_*chi 6

简答

我广泛查看了文档,目前在 Lodash 4.17.15 中(截至 2021 年 1 月 26 日)似乎库中没有直接实现此类功能。因此:

_.map(columns, row => _.pick(row, 'key'))

//Output, when using the columns collection I introduce below:
//[{key: "url"},
// {key: "user"},
// {}]
Run Code Online (Sandbox Code Playgroud)

应被视为首选解决方案。如果找不到密钥:

  • 钥匙不会附着在物体上
  • 你会得到一个空的对象

长答案

我认为值得注意的是替代方法的优点和缺点。让我们对它们进行一下浏览,考虑以下集合,旨在显示每个解决方案可能出现的一些缺点:

var columns = [
    { 0: 'pos_url', key:'url', width:20, type:'text' },
    { 1: 'pos_user', key:'user', width:24, type:'text' },
    "key"
];
Run Code Online (Sandbox Code Playgroud)

如果您愿意,请尝试 Codepen 上解释的所有方法!

这可能有点乱,但我实际上写了一个小代码笔,你可以把手弄脏并尝试这里解释的所有内容,请随意尝试:

https://codepen.io/jhack_jos/pen/gOwVReB

您必须打开浏览器控制台才能查看 console.log 输出。

1)使用“项目”功能

如果像我一样,您实际上不想使用 mixins 并与 Lodash 混淆,您也可以使用我创建的以下函数,称为project. 它的灵感来自 Michael Fogus“函数式 JavaScript”,因为他在有关“类表”数据和“应用程序编程”的演讲中引入了类似的函数。这个名字来源于关系代数中称为投影的一元运算它的作用非常相似。

与ES6

function project(...properties)
{
  return function project(object, index, array)
    {
      return _.pick(object, ...properties);
    };
}
Run Code Online (Sandbox Code Playgroud)

没有 ES6

function project(/* properties here */)
{
  var properties = arguments;
  return function project(object, index, array)
    {
      return _.pick.bind(null, object).apply(null, properties);
    };
}
Run Code Online (Sandbox Code Playgroud)

一些用法示例:

_.map(columns, project("key"));

//Output:
//[{key: "url"},
// {key: "user"},
// {}]

_.map(columns, project("key", "width"));

//Output:
//[{key: "url", width: 20},
// {key: "user", width: 24},
// {}]

_.map(columns, project("key", ["width", "type"]));

//Output:
//[{key: "url", width: 20, type: "text"},
// {key: "user", width: 24, type: "text"},
// {}]
Run Code Online (Sandbox Code Playgroud)

的不同实现有多快project

  • ES6 实现始终是最快的
  • 如果没有 ES6,在 V8 上,bind + apply 组合是我发现的最快的实现。在 SpiderMonkey 上,即使差距很小,使用 Array.prototype.concat 也会更快。您可以在下面的链接中找到这样的实现。
  • 链接到 jsbench.me 上的测试,还包含其他可能的实现projecthttps://jsbench.me/2gkkfl9pw4

如果找不到密钥:

  • 钥匙不会附着在物体上
  • 你会得到一个空的对象

2)_.mapPick方法

我实际上非常喜欢 @pery mimon 在问题中使用的 mixin 方法。也可以_.chain与它一起使用,这使得代码非常可读。请记住与未来 Lodash 更新发生冲突的可能性。不幸的是,当将属性列表作为参数抛出时,该算法的行为并不像人们预期的那样(它忽略除第一个参数之外的所有参数)。我可能会建议以下改进:

与ES6

_.mixin({
    mapPick:  function (objs, ...keys) {
        return _.map(objs, function (obj) {
            return _.pick(obj, ...keys);
        })
    }
});
Run Code Online (Sandbox Code Playgroud)

没有 ES6

_.mixin({
    mapPick:  function (objs) {
        var properties = arguments;
        return _.map(objs, function (obj) {
            return _.pick.bind(null, obj).apply(null, properties);
        })
    }
});
Run Code Online (Sandbox Code Playgroud)

多亏了这一点,我们现在可以做到:

_.mapPick(columns, "key", "width")

//Output now:
//[{key: "url", width: 20}
// {key: "user", width: 24}
// {}]

//Output of the original mixin from the question:
//[{key: "url"}
// {key: "user"}
// {}]
Run Code Online (Sandbox Code Playgroud)

如果找不到密钥:

  • 钥匙不会附着在物体上
  • 你会得到一个空的对象

3) _.partialRight 方法

不建议使用这种方法,因为如果在边缘情况场景中应用不当,可能会显得很棘手。Lodash 文档指出_.partialRight执行以下操作:

此方法类似于 _.partial,只不过部分应用的参数附加到它接收的参数中。

这意味着_.partialRight(func, arg1, arg2) (arg3, arg4)解析为func(arg3, arg4, arg1, arg2).

错误的做法

因此,以下代码:

_.map(columns, _.partialRight(_.pick, 'key'));
Run Code Online (Sandbox Code Playgroud)

解析为:

_.map(columns, (row, index, columns) => _.pick(row, index, columns, 'key'));

//Output:
//[{0: "pos_url", key: "url"},
// {1: "pos_user", key: "user"},
// {2: "y"}]
Run Code Online (Sandbox Code Playgroud)

如果找不到密钥:

  • 钥匙不会附着在物体上
  • 你会得到一个空的对象

正确的做法

因此,您应该将_.unary向下传递的参数限制_.pick为只有一个。代码如下:

_.map(columns, _.unary(_.partialRight(_.pick, 'key')));
Run Code Online (Sandbox Code Playgroud)

这解决了:

_.map(columns, (row, index, columns) => _.pick(row, 'key'));

//Output:
//[{key: "url"},
// {key: "user"},
// {}]
Run Code Online (Sandbox Code Playgroud)

如果找不到密钥:

  • 钥匙不会附着在物体上
  • 你会得到一个空的对象

4) 解构和箭头函数

您可能期望这种方法能够覆盖所有内容并且是普通的,但您可能会发现它在边缘情况下稍微不灵活。我们来看看:

columns.map(({key}) => ({key}))

//Output:
//[{key: "url"},
// {key: "user"},
// {key: undefined}]
Run Code Online (Sandbox Code Playgroud)

一些相关事实:

  • 你不能选择数字键
  • 你不能选择包含空格的键

如果找不到密钥:

  • 你将得到一个值为“undefined”的键
  • 你永远不会得到一个空的对象
  • _.keys仍会返回未找到的密钥

5) 提取没有键的值

这是一个额外的,不符合问题。正如另一个答案指出的那样,如果您不需要键,您可以使用_.map快捷方式(以前称为_.pluck)提取值:

_.map(columns, "key")

//Output:
//["url", "user", undefined]
Run Code Online (Sandbox Code Playgroud)

关于这种方法有很多有趣的事情需要了解,因为它隐式地使用了_.iteratee函数,这使我们能够如此出色地使用_.get_.map

如果找不到密钥:

  • 未定义将用作值
  • 您将得到一个与原始长度相同的数组,但填充了“未定义”值


Met*_*orm 5

如果您只想要其中一个键,则可以执行以下操作:

_.map(collection, 'key')
Run Code Online (Sandbox Code Playgroud)

你的例子:

var columns = [
    { key:'url', width:20, type:'text' },
    { key:'title', width:21, type:'text' },
    { key:'desc', width:22, type:'text' },
    { key:'domain', width:23, type:'text' },
    { key:'user', width:24, type:'text' }
];

var widths = _.map(columns, 'width');

widths
[20, 21, 22, 23, 24]
Run Code Online (Sandbox Code Playgroud)