使用 ramda.js 将对象数组转换为一个对象

Convert array of objects to one Object using ramda.js

我有一个数组:

var a = [
    {id: 1, val: 'a'},
    {id: 2, val: 'b'},
    {id: 3, val: 'c'},
    {id: 4, val: 'd'},
]

我想将其转换为:

var b = {
    1: 'a',
    2: 'b',
    3: 'c',
    4: 'd',
}

其实我用的是纯js:

var b = a.reduce(
    (ac, pr) => ({
      ...ac,
      [pr.id]: pr.val,
    }),
    {}
  );

但也许 Ramda.js 有什么特殊用途?

您正在寻找 Ramda 的 .mergeAll() method:

var b = R.mergeAll(a.map(function(o) {
  return {
    [o.id]: o.val
  }
}));

.map()调用将return每个项目的自定义对象,只取值,然后.mergeAll()array合并为一个object.

mergeAll 文档:

Merges a list of objects together into one object.

演示:

var a = [{
    id: 1,
    val: 'a'
  },
  {
    id: 2,
    val: 'b'
  },
  {
    id: 3,
    val: 'c'
  },
  {
    id: 4,
    val: 'd'
  },
];


var b = R.mergeAll(a.map(function(o) {
  return {
    [o.id]: o.val
  }
}));
console.log(b);
<script src="https://cdn.jsdelivr.net/ramda/0.18.0/ramda.min.js"></script>

对于纯 Javascript,您可以使用 Object.assign, spread syntax ..., Array#map, destructuring assignment and short hand properties 的组合。

var a = [{ id: 1, val: 'a' }, { id: 2, val: 'b' }, { id: 3, val: 'c' }, { id: 4, val: 'd' }],
    result = Object.assign(...a.map(({ id, val }) => ({ [id]: val })));

console.log(result);

var a = [
    {id: 1, val: 'a'},
    {id: 2, val: 'b'},
    {id: 3, val: 'c'},
    {id: 4, val: 'd'},
]

var result = {};
for (var i=0; i<a.length; i++) {
  result[a[i].id] = a[i].val;
}

console.log(result);

如果你想要一些免积分的东西,你可以写:

const combine = compose(mergeAll, map(lift(objOf)(prop('id'), prop('val'))))

const {compose, mergeAll, map, lift, objOf, prop} = R;

const combine = compose(mergeAll, map(lift(objOf)(prop('id'), prop('val'))))

var a = [{id:1, val:'a'}, {id:2, val:'b'}, {id:3, val:'c'}, {id:4, val:'d'}]
console.log(combine(a));
<script src="https://cdn.jsdelivr.net/ramda/0.18.0/ramda.min.js"></script>

在这里它就像一个魅力:

var a = [
    {id: 1, val: 'a'},
    {id: 2, val: 'b'},
    {id: 3, val: 'c'},
    {id: 4, val: 'd'},
];
// var b = R.fromPairs( a.map(Object.values) );
// Perhaps this is the more general and order independent way:
var b = R.fromPairs(a.map( ({id,val})=>[id,val] ));
console.log( b );
<script src="//cdn.jsdelivr.net/npm/ramda@latest/dist/ramda.min.js"></script>

通过映射R.props, and use R.fromPairs从每个对象中获取有序值以创建对象:

var a = [
    {id: 1, val: 'a'},
    {id: 2, val: 'b'},
    {id: 3, val: 'c'},
    {id: 4, val: 'd'},
];

var result = R.compose(R.fromPairs, R.map(R.props(['id', 'val'])));

console.log(result(a));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

最简单,无意义:

compose(fromPairs, map(values))(a)

const { compose, fromPairs, map, values } = R

const a = [
    {id: 1, val: 'a'},
    {id: 2, val: 'b'},
    {id: 3, val: 'c'},
    {id: 4, val: 'd'},
]

const result = compose(fromPairs, map(values))(a)

console.log(result)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

如果还有人路过这里,确实是:

R.indexBy(R.prop('id'), someArray);

See indexBy in Ramda's documentation

编辑: 班纳特是正确的。如果我们希望 val 作为每个键的唯一值,我们可以在之后“提取”它:

const createValDict = R.pipe(
  R.indexBy(R.prop('id')),
  R.pluck('val')
)

const valDict = createValDict(myArr)

Pluck works on objects too

这可能是最简单的方法:

pipe(map(props(['id', 'val'])), fromPairs)(a)

更简单,但不能保证在所有平台上都能正常工作。 Ramda 代码高尔夫总是很有趣!

const { fromPairs, map, pipe, props } = R

const a = [
    {id: 1, val: 'a'},
    {id: 2, val: 'b'},
    {id: 3, val: 'c'},
    {id: 4, val: 'd'},
]

const result = pipe(map(props(['id', 'val'])), fromPairs)(a)

console.log(result)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.min.js"></script>

还有一种方法:

const { indexBy, prop, pipe, pluck } = R
const a = [
    {id: 1, val: 'a'},
    {id: 2, val: 'b'},
    {id: 3, val: 'c'},
    {id: 4, val: 'd'},
]
const result = pipe(indexBy(prop('id')), pluck('val'))(a)
console.log(result)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.min.js"></script>