Javascript 哈希表的对象数组
要转换(使用Ramda) 进入 我对函数式编程非常陌生,我对任何想法都持开放态度 我认为我们必须做的是,使用一个从{}开始的reduce函数,然后我们希望在每次迭代中将当前元素的id和名称添加到哈希表中。这是我提出的,看起来非常错误。我接近了吗Javascript 哈希表的对象数组,javascript,ramda.js,Javascript,Ramda.js,要转换(使用Ramda) 进入 我对函数式编程非常陌生,我对任何想法都持开放态度 我认为我们必须做的是,使用一个从{}开始的reduce函数,然后我们希望在每次迭代中将当前元素的id和名称添加到哈希表中。这是我提出的,看起来非常错误。我接近了吗 var a = [{id: 1, name: 'one'}, {id: 2, name: 'two'},{id: 3, name: 'three'},{id: 4, name: 'four'} ] var b = R.reduce(R.assoc(R.p
var a = [{id: 1, name: 'one'}, {id: 2, name: 'two'},{id: 3, name: 'three'},{id: 4, name: 'four'} ]
var b = R.reduce(R.assoc(R.prop('id'), R.prop('name')), {}, a)
b
您可以通过以下方式实现这一点:
var a = [{id: 1, name: 'one'}, {id: 2, name: 'two'},{id: 3, name: 'three'}]
var b = R.reduce((dict, item) => ({ ...dict, [ item.id ] : item.name }), {}, a)
此方法使用es6语法,在每次还原迭代期间,将带有值(item.name
)的键(通过item.id
)添加到生成的词典中。尝试使用以下代码:
var a = [{id: 1, name: 'one'}, {id: 2, name: 'two'},{id: 3, name: 'three'}]
R.map(i=> {
var n = []
n[R.keys(i)[0]] = i.name
return n
},a)
使用es6时,您可以获得更灵活的解决方案
a=[{id:1,name:'one'},{id:2,name:'two'},{id:3,name:'twree'}];
释放=a.reduce((acc,{id,name})=>{
acc[id]=名称;
返回acc;
}, {});
console.log(out)
您可以循环初始数组并分配给新对象:
var a=[{id:1,名称:'one'},{id:2,名称:'two'},{id:3,名称:'twree'}];
var new_a={};
a、 forEach(函数(e){
new_a[e.id]=e.name;
});
控制台日志(新的)代码>您可以创建管道()将对象数组转换为哈希:
获取每个()对象的属性()的值
将成对数组转换为对象()
const a=[{id:1,name:'one'},{id:2,name:'two'},{id:3,name:'three'}];
const convertToHash=(道具)=>
右管(
R.map(R.props(props)),
R.fromPairs
);
const result=convertToHash(['id','name'])(a);
控制台日志(结果)代码>
有很多方法可以解决这个问题。所有其他正确答案都有助于说明这一点。我会在下面列出我自己的一些。但首先,
为什么你的方法不起作用
您尝试这样做:
R.reduce(R.assoc(R.prop('id'), R.prop('name')), {}, a)
很清楚你想在这里做什么。问题在于R.prop('id')
和R.prop('name')
都是函数<代码>R.assoc
不接受函数;它需要一个字符串(实际上是一个数字)和一个任意值。因此,assoc
将不会以这种方式使用它们
清理这个问题的一个尝试是认识到函数可以被看作是值的容器。在某种程度上——也许令人惊讶,但非常有用——函数是其返回值的容器。旨在将处理值的函数转换为处理值容器的函数。它的工作原理如下:R.multiply
接受数字。如果我们提升乘法
,结果函数将接受数字容器。像这样:
R.lift(R.multiply)(Maybe.Just(5), Maybe.Just(3)) // Maybe.Just(15)
如果我们提供了两个函数lift(multiply)
,那么我们将返回一个函数,该函数返回其返回值相乘的结果:
const area = R.lift(R.multiply)(prop('width'), prop('height'))
area({width: 5, height: 3})
因此,也许我们可以用升降机更新您的技术:
R.reduce(R.lift(R.assoc)(R.prop('id'), R.prop('name'), identity), {}, a)
不幸的是,这又失败了。这次的问题是reduce
接受二进制回调,同时提供累加器和当前值。但是R.prop('id')
和R.prop('name')
不承认这一点。他们寻找累加器上的相关属性,而这些属性根本不存在
我们可能仍然能够解决这个问题,但在这一点上,我们将失去这个解决方案的许多简单性。让我们看看其他的可能性
一些解决方案
简单还原
这两个版本中的每一个都使用一个简单的reduce
调用,正如您的解决方案所尝试的那样:
const convertToHash = reduce((acc, {id, name}) => merge(acc, {[id]: name}), {})
及
他们几乎一样。两者都在每次迭代中创建一次性对象。在第一种方法中,您可以将R.merge
替换为Object.assign
,而不存在任何实际问题,因为产生的变异是函数内部的。第二个看起来稍微优雅一些,但它在每次迭代中都会重建整个累加器。随着ES6引擎优化的进行,这可能最终不会成为性能问题,但现在可能是,特别是在性能关键代码中
使用zipWith
Ramda的zip
函数采用两个列表,并将它们逐位置合并到一个列表中。接受用于将两个元素合并为一个元素的函数。这里我们使用,它将名称和值转换为单个属性对象。(objOf('foo',42)/=>{foo:42}
):
如上所述,我们使用lift
使这个zipWith(objOf)
与函数一起工作。这会产生类似于[{“1”:“one”}、{“2”:“two”}、{“3”:“three”}]
的结果,然后将其传递给创建单个对象
使用props
和fromPairs
此解决方案使用和fromPairs
接受名称-值对列表(作为两个元素数组),并将它们转换为单个对象<代码>道具
将命名属性拉入独立数组。在原始列表上,这为我们提供了从配对到的输入:
const convertToHash = compose(fromPairs, map(props(['id', 'name'])))
虽然我喜欢zipWith
解决方案,并且如果它的输出是我想要的,我会使用它,但是必须添加mergeAll
,这使得它更难一眼理解。所以这个解决方案在我看来是最好的Ramda选择 一般来说,如果答案中包含对代码意图的解释,以及在不介绍其他代码的情况下解决问题的原因,那么答案会更有帮助。这个答案需要减少!这确实帮助我理解了这个问题。非常感谢。
const convertToHash = reduce((acc, {id, name}) => merge(acc, {[id]: name}), {})
const convertToHash = reduce((acc, {id, name}) => ({...acc, [id]: name}), {})
const convertToHash = compmose(mergeAll, lift(zipWith(objOf))(pluck('id'), pluck('name')))
const convertToHash = compose(fromPairs, map(props(['id', 'name'])))