-1

I am using Ramda library in my project.

is it possible to transform following JSON array

from

[
   {
     "id": 1,
     "name": "test",
   },
   {
     "id": 2,
     "name": "test2"
   }

];

To

[
   {
     "id": 1,
     "id": 2,

   },
   {
     "name": "test",
     "name": "test2"
   }

];

pleas help

MAnI
  • 57
  • 5
  • 2
    You can’t have the same key multiple times on a keyed collection; your expected result, as an expression, will result in an array of two objects, each having a single property (`id` and `name` respectively, with values `2` and `"test2"`, respectively), as only the last key with the same name is kept in the result. – Sebastian Simon Apr 07 '21 at 08:00

2 Answers2

1

Objects can't have multiple properties with the same key, so { "id": 1, "id": 2 } and { "name": "test", "name": "test2" } are invalid. I assume that you need an array of ids and an array of names:

[[1, 2, 3], ['test', 'test2', 'test3']]

If all objects are have the same order of keys - ie no { id: 1, name: 'test'} and { name: 'test2', id: 1 }, and you need all the values in an object, you can map the objects to their values, and then transpose:

const { pipe, map, values, transpose } = R;

const fn = pipe(
  map(values),
  transpose,
);

const arr = [{"id":1,"name":"test"},{"id":2,"name":"test2"},{"id":3,"name":"test3"}];

const result = fn(arr);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>

If some objects have a different keys insertion order, you want to change the order of the resulting arrays, or if you need some of the keys, you can get the values with R.props, and then transpose:

const { pipe, map, props, transpose } = R;

const fn = pipe(
  map(props(['name', 'id'])), // example - name would be the 1st sub-array
  transpose,
);

const arr = [{"id":1,"name":"test"},{"id":2,"name":"test2"},{"id":3,"name":"test3"}];

const result = fn(arr);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>

If you want the structure suggested by Scott Sauyet's:

{
  id: [1, 2],
  name: ['test1', 'test2']
}

I would map and flatten the objects to an array of pairs with R.chain and R.toPairs, group them by the 1st item in each pair (the original key), and then map each groups item to the last item in each pair (the original value).

const { pipe, chain, toPairs, groupBy, head, map, last } = R

const fn = pipe(
  chain(toPairs),
  groupBy(head),
  map(map(last)), // map(pipe(map(last), uniq)) if you want only unique items
) 

const arr = [{"id":1,"name":"test"},{"id":2,"name":"test2"},{"id":3,"name":"test3"}];

console.log(fn(arr))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
1

As OriDrori pointed out, your requested output is not valid JS. I'm going to make a slightly different guess, though, as to a useful variant of it that is valid, namely that we want an output like this:

{
  id: [1, 2],
  name: ['test1', 'test2']
}

Here's one simple way to achieve that in vanilla JS:

const extract = (data) => {
  const keys = [... new Set (data .flatMap (Object .keys))]
  return Object .fromEntries (
    keys.map (k => [k, data .map (o => o [k])])
  )
}

const data = [{id: 1, name: "test"}, {id: 2, name: "test2"}]

console .log (
  extract (data)
)

We can definitely clean that up with Ramda functions. Another version might look like this:

const extract = (data) => fromPairs (
  map (k => [k, map (o => o [k], data)]) (uniq (chain (keys) (data)))
)

const data = [{id: 1, name: "test"}, {id: 2, name: "test2"}]

console .log (extract (data))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js"></script>
<script> const {fromPairs, map, uniq, chain, keys} = R                     </script>

While we could go completely point-free, I find this version much less readable:

const extract = compose (
  fromPairs, 
  lift (map) (
    unary (compose (ap (pair), flip (pluck))), 
    compose (uniq, chain (keys))
  )
) 

const data = [
   {id: 1, name: "test"},
   {id: 2, name: "test2"}
]

console .log (extract (data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js"></script>
<script> 
  const {compose, fromPairs, lift, map, unary, ap, pair, flip, pluck, uniq, chain, keys} = R 
</script>
Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103