Max Kachanov
Max Kachanov

Reputation: 113

Ramda reduce from array to object?

How can I switch from array to object data type in pipeline using ramda's reduce in point-free style?

I would like to achieve this:

(nodes) => nodes.reduce((acc, node: any) => {
  acc[node.id] = {
    out: node.outgoing_explicit,
    in: node.incoming_explicit
  };
  return acc;
}, {})

Upvotes: 2

Views: 635

Answers (3)

Scott Sauyet
Scott Sauyet

Reputation: 50797

The solutions involving applySpec are probably best, but just for variety, here's an alternative:

const convert  = pipe (
  map (juxt ([prop('id'), props(['incoming_explicit', 'outgoing_explicit'])])),
  fromPairs,
  map (zipObj (['in', 'out']))
)

const nodes = [{id: 'foo', outgoing_explicit: 43, incoming_explicit: 42}, {id: 'bar', outgoing_explicit: 20, incoming_explicit: 10}, {id: 'baz', outgoing_explicit: 309, incoming_explicit: 8675}]

console .log (convert (nodes))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script>const {pipe, map, juxt, prop, props, fromPairs, zipObj} = R        </script>

`juxt' is a bit of an oddball function. It works like this:

juxt([f, g, h, ...]) //=> (a, b, ...) -> [f(a, b, ...), g(a, b, ...), h(a, b, ...), ...]

Upvotes: 1

Hitmands
Hitmands

Reputation: 14179

this could also be a solution:

const spec = {
  in: R.prop('incoming_explicit'),
  out: R.prop('outgoing_explicit'),
}
  
const fn = R.reduceBy(
  R.flip(R.applySpec(spec)),
  null,
  R.prop('id'),
);

const data = [
  { id: 'a', incoming_explicit: 'Hello', outgoing_explicit: 'World' },
  { id: 'b', incoming_explicit: 'Hello', outgoing_explicit: 'Galaxy' },
  { id: 'c', incoming_explicit: 'Hello', outgoing_explicit: 'Universe' },
  { id: 'd', incoming_explicit: 'Hello', outgoing_explicit: 'Dimension' },
];

console.log(
  fn(data),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous"></script>

Upvotes: 2

Ori Drori
Ori Drori

Reputation: 191986

Index the nodes by id, and the map them and use R.applySpec to change to the in/out format:

const { pipe, indexBy, map, applySpec, prop } = R

const fn = pipe(
  indexBy(prop('id')),
  map(applySpec({
    out: prop('outgoing_explicit'),
    in: prop('incoming_explicit'),
  }))
)

const nodes = [{ id: 1, outgoing_explicit: 'abc1', incoming_explicit: 'xyz1' }, { id: 2, outgoing_explicit: 'abc2', incoming_explicit: 'xyz2' }, { id: 3, outgoing_explicit: 'abc3', incoming_explicit: 'xyz3' }]

const result = fn(nodes)

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>

Upvotes: 2

Related Questions