lodash:将数组映射到对象


90

是否有内置的lodash函数来执行此操作:

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];

并输出:

var output = {
    foo: 'bar',
    baz: 'zle'
};

现在我正在使用Array.prototype.reduce()

function toHash(array, keyName, valueName) {
    return array.reduce(function(dictionary, next) {
        dictionary[next[keyName]] = next[valueName];
        return dictionary;
    }, {});
}

toHash(params, 'name', 'input');

想知道是否有lodash捷径。

Answers:


132

lodash的另一种方式4.17.2

_.chain(params)
    .keyBy('name')
    .mapValues('input')
    .value();

要么

_.mapValues(_.keyBy(params, 'name'), 'input')

或搭配 _.reduce

_.reduce(
    params,
    (acc, { name, input }) => ({ ...acc, [name]: input }),
    {}
)

@Akrikos_.keyBy将把整个数组转换为一个对象,而问题主要是关于将数组中每个对象的一项作为键,将另一项作为其值。如果_.keyBy使用,则所有值均为对象。
Mustafa Ehsan Alokozay

谢谢@MustafaEhsanAlokozay你说的对,这个答案做的并不正确。我将删除我的评论,因为它没有帮助。这可能会使您的评论看起来很怪异,但总比让我的不正确评论留下来更好。
Akrikos

53

您应该使用_.keyBy轻松将数组转换为对象。

文件在这里

用法示例如下:

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];
console.log(_.keyBy(params, 'name'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

如果需要,可以在使用_.keyBy之前操纵数组,或者在使用_.keyBy之后操纵对象以获得确切的所需结果。


2
首先查看此内容,以了解stasovlas投票最多的答案。
罗曼·苏西

3
这是一个很酷的答案,但不能回答这个问题。值应该是字符串而不是对象。
Dem Pilafian

34

是的,在这里,使用_.reduce

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];

_.reduce(params , function(obj,param) {
 obj[param.name] = param.input
 return obj;
}, {});

再一次reduce()涌入另一个用例。聪明的做法!

有人得到了这个版本的打字稿吗?
Mr.bjerre

实际上,从数学上讲,您可以使用reduce / inject实现任何迭代操作,因为reduce对列表是同构的。但是,这种灵活性带来了可读性的代价。_.reduce除非能准确地表达您要执行的操作,否则不要使用:在任何其他情况下,它都会明显掩盖代码的要点。我个人更喜欢_.zipObject@djechlin的解决方案-否则,_.keyBy/_.mapValues方法。
罗伯特·菲舍尔

15

这似乎是Object.assign的工作:

const output = Object.assign({}, ...params.map(p => ({[p.name]: p.input})));

编辑为包装成类似于OP的功能,这将是:

const toHash = (array, keyName, valueName) => 
    Object.assign({}, ...array.map(o => ({[o[keyName]]: o[valueName]})));

(感谢Ben Steward,好主意...)


也许将其包装在父函数中,以便用户可以像OP一样通过传递键来确定将使用哪些键。
Ben Steward


10

这可能比您想要的要冗长得多,但是您要求的是稍微复杂的操作,因此可能会涉及到实际代码(恐怖)。

我的建议zipObject很合乎逻辑:

_.zipObject(_.map(params, 'name'), _.map(params, 'input'));

另一个选择,更hacky,使用fromPairs

_.fromPairs(_.map(params, function(val) { return [val['name'], val['input']));

匿名函数显示出骇人行为-我不相信JS保证对象迭代中元素的顺序,因此调用.values()不会这样做。


我看不到有关使用的任何技巧fromPairs,调用values()确实不会。至少从可读性的角度来看。
x-yuri

6

Lodash的另一种方式

创建对,然后构造一个对象或ES6 Map轻松地

_(params).map(v=>[v.name, v.input]).fromPairs().value()

要么

_.fromPairs(params.map(v=>[v.name, v.input]))

这是一个有效的例子


1
该解决方案的优点在于它在纯ES中也可行:Object.fromEntries(params.map(v => [v.name, v.input]))
fregante

@fregante,仅适用
d9k

6

它也可以不使用像这样的lodash函数来解决:

let paramsVal = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];
let output = {};

paramsVal.forEach(({name, input})=>{
  output[name] = input;
})


console.log(output);

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.