我有以下系列:
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' }
];
我正在寻找一种方法来映射带有拾取键的对象数组,这些方法符合以下几点:
_.mapPick(columns, [width])
// [{width:20},{width:21},{width:22},{width:23},{width:24}]
我知道我可以像这样扩展lo-dash:
_.mixin({
mapPick: mapPick:function (objs,keys){
return _.map(objs, function (obj) {
return _.pick(obj,keys)
})
}
});
我不确定是否有一些我缺少的原生功能。
我发现了一个类似的问题here,但我正在寻找一种更为低调的本土方式。
答案 0 :(得分:22)
答案 1 :(得分:18)
在我的情况下我还需要强制转换类型,而问题是TS编译器代表Adam Boduch解决方案返回一个布尔值,所以我找到一个简单的方法来做到这一点:
_.map(columns, item => { return { key: item.key } });
在这种情况下,您还可以添加一些新属性。
P.S。因为我无法发表评论,所以我将在此处添加有关partialRight用法的说明:
_.map(columns, _.partialRight(_.pick, 'key'));
首先如果您调用_.map(array, func)
func 将为每个数组元素调用。所以它是平等的:_.map(array, item => func(item))
。
第二次调用 partialRight 的结果将是一个函数 newFunc ,因此我们可以将Adam的代码表示为:
var newFunc = _.partialRight(_.pick, 'key');
_.map(array, item => newFunc(item));
第三次我们可以将 newFunc 逻辑表示为:
function newFunc(item) {
return _.pick(item, 'key')
}
最后我认为这个问题最容易理解和最易读的解决方案是:
_.map(columns, item => _.pick(item, 'key'))
答案 2 :(得分:12)
我在map examples中找到了更简单的解决方案:
var users = [
{name:'David',age:35},
{name:'Kate',age:28},
];
_.map(users,'age'); // [35,28]
答案 3 :(得分:4)
如果您只想要其中一个键,那么:
_.map(collection, 'key')
你的例子:
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]
答案 4 :(得分:3)
我广泛地研究了 the docs,目前在 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"},
// {}]
应被视为首选解决方案。 如果未找到密钥:
我认为,替代方法可能存在哪些优点和缺点,可能值得一提。让我们来看看它们之间的关系,考虑以下集合,旨在展示每个解决方案可能出现的一些缺点:
var columns = [
{ 0: 'pos_url', key:'url', width:20, type:'text' },
{ 1: 'pos_user', key:'user', width:24, type:'text' },
"key"
];
这可能有点乱,但我实际上写了一个小代码笔,如果你可以弄脏你的手并尝试这里解释的所有内容,请随意尝试:
https://codepen.io/jhack_jos/pen/gOwVReB
您必须打开浏览器控制台才能看到 console.log 输出。
如果和我一样,你真的不想使用 mixins 和 Lodash 搞混,你也可以使用我创建的以下函数,称为 project
。它的灵感来自 Michael Fogus “Functional JavaScript”,因为他在其关于“Table-Like”数据和“Applicative Programming”的演讲中介绍了一个类似的函数。该名称来自关系代数中名为 projection 的一元运算,其作用非常相似。
使用 ES6
function project(...properties)
{
return function project(object, index, array)
{
return _.pick(object, ...properties);
};
}
没有 ES6
function project(/* properties here */)
{
var properties = arguments;
return function project(object, index, array)
{
return _.pick.bind(null, object).apply(null, properties);
};
}
一些用法示例:
_.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"},
// {}]
project
的不同实现有多快?
project
的其他可能实现:https://jsbench.me/2gkkfl9pw4如果没有找到密钥:
我真的很喜欢@pery mimon 在问题中使用的 mixin 方法。也可以将 _.chain
与它一起使用,这使得代码非常易读。请记住与未来的 Lodash 更新发生冲突的可能性。不幸的是,当将属性列表作为参数抛出时,该算法的行为并不像人们预期的那样(它忽略除第一个参数之外的所有参数)。我可能会建议以下改进:
使用 ES6
_.mixin({
mapPick: function (objs, ...keys) {
return _.map(objs, function (obj) {
return _.pick(obj, ...keys);
})
}
});
没有 ES6
_.mixin({
mapPick: function (objs) {
var properties = arguments;
return _.map(objs, function (obj) {
return _.pick.bind(null, obj).apply(null, properties);
})
}
});
多亏了这一点,我们现在可以做到:
_.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"}
// {}]
如果没有找到密钥:
不推荐这种方法,因为如果在边缘情况下错误地应用它可能会显得很棘手。 Lodash docs 声明 _.partialRight
执行以下操作:
此方法类似于 _.partial,只是部分应用了参数 附加到它收到的参数。
这意味着 _.partialRight(func, arg1, arg2) (arg3, arg4)
解析为 func(arg3, arg4, arg1, arg2)
。
因此,以下代码:
_.map(columns, _.partialRight(_.pick, 'key'));
解析为:
_.map(columns, (row, index, columns) => _.pick(row, index, columns, 'key'));
//Output:
//[{0: "pos_url", key: "url"},
// {1: "pos_user", key: "user"},
// {2: "y"}]
如果没有找到密钥:
因此,您应该使用 _.unary
将传递给 _.pick
的参数限制为只有一个。代码如下:
_.map(columns, _.unary(_.partialRight(_.pick, 'key')));
这解析为:
_.map(columns, (row, index, columns) => _.pick(row, 'key'));
//Output:
//[{key: "url"},
// {key: "user"},
// {}]
如果没有找到密钥:
您可能期望这种方法涵盖所有内容并且是普通的,但您可能会发现它在边缘情况下有点不灵活。我们来看看:
columns.map(({key}) => ({key}))
//Output:
//[{key: "url"},
// {key: "user"},
// {key: undefined}]
一些相关事实:
如果没有找到密钥:
_.keys
仍会返回未找到的密钥这是一个额外的,不符合问题。正如另一个答案指出的那样,如果您不需要这些键,您可以使用 _.map
快捷方式(以前称为 _.pluck
)提取值:
_.map(columns, "key")
//Output:
//["url", "user", undefined]
关于这种做法有很多有趣的事情需要了解,因为它隐式地使用了 _.iteratee 函数,这使我们能够将 _.get 与 { {1}} .
如果没有找到密钥:
答案 5 :(得分:2)