2

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;
}, {})

3 Answers 3

2

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>

Sign up to request clarification or add additional context in comments.

Comments

2

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>

Comments

1

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, ...), ...]

2 Comments

Would juxt be classified as a transducer?
@Redark: No, the Ramda functions that can act as transducers have a special annotation in their documentation: "Acts as a transducer if a transformer is given in list position." This one does not, and is not a transducer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.