简体   繁体   中英

Convert array of objects to one Object using ramda.js

I have an array:

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

And I want to get transform it to:

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

Actually I'm using pure js:

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

But maybe Ramda.js have something special for that purpose?

You are looking for Ramda's .mergeAll() method :

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

The .map() call will return the custom object from each item, taking only the values, then .mergeAll() will merge the array into one object .

mergeAll Documentation :

Merges a list of objects together into one object.

Demo:

 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>

If anyone still passes by here, it does indeed:

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

See indexBy in Ramda's documentation

EDIT: Bennet is correct. If we want val as the only value per key, we can "pluck" it out after:

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

const valDict = createValDict(myArr)

Pluck works on objects too

Get the ordered values from each object by mapping with R.props , and use R.fromPairs to create an object:

 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>

With plain Javascript, you could use a combination with 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);

If you wanted something point-free, you could write:

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>

Here it works like a charm :

 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>

Simplest, point-free:

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>

This might be the simplest way:

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

@spflow's answer is simpler but not guaranteed to work on all platforms. Ramda code golf is always fun!

 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>

Yet one approach:

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM