1

In an interview, I was asked to hit the jsonplaceholder /posts and /comments endpoints and write a function that returns matched comments with posts where comment.postId == post.id then make a whole JSON object containing the post within the comments belongs to it.

I have been trying to implement it in a functional approach but cannot find a way of dealing with 2 arrays (2 inputs) as pipelines, compositions, transducers all accept unary functions.

I Even thought of having two pipelines one for processing the comments and the other for posts and joining their workflows at the end but couldn't implement it.

All I could come up with is mapping the comments themselves to be an array of objects where it has postId as a number that represents each post and comments as array of strings

import axios from 'axios'
import _ from 'ramda'

const { data: comments } = await axios.get(
  'http://jsonplaceholder.typicode.com/comments',
)

const cIds = (comments) =>
  _.pipe(
    _.groupBy(_.prop('postId')),
    _.map(_.pluck('body')),
    _.map(_.flatten),
    _.map(_.uniq),
    _.toPairs,
    _.map(_.zipObj(['postId', 'comments'])),
  )(comments)

console.log(cIds(comments))

So anyone has an idea of how to do so in a functional manner?

  • 1
    What do you mean here by "in a functional manner"? To me that means working with pure functions, not mutating data, and creating no side effects (and some other things.) Are you looking for a point-free solution? If so, I would suggest that should come later, once you have working code, and then not at all unless it makes the code more readable. – Scott Sauyet Nov 17 '21 at 21:40
  • Just as you described it, I was trying to implement it by making pure functions or rather a pipeline of functions that produces the expected output, but I was stumbled by how can I do it for using the two inputs, as far as I know, function composition, pipelines only work with unary functions, not binary ones. And no, I am not looking for a point-free solution (yet), as you recommended, I am just trying to have it working as expected. – Ahmed Osama Nov 17 '21 at 21:51
  • Highly relevant [Q&A](https://stackoverflow.com/a/42139851/633183) – Mulan Nov 19 '21 at 05:05
  • I already understand the idea of currying and composition, but I was thinking of a way - if possible - to make a pipeline on maybe array X and the output can be piped to another pipeline that was working on array Y and perform some computation of the inputs as in [X, Y] and maybe the output of the second pipeline can be an array of Z I think that's more like streams when you pipe the output of a stream as an input to another stream but couldn't implement it on my own. – Ahmed Osama Nov 19 '21 at 21:48

1 Answers1

0

I think I'm missing something in the question. This sounds like a fairly simple function. I might write it something like this:

const consolidate = ([posts, comments]) => 
  posts .map (p => ({
    ...p,
    comments: comments .filter (c => c.postId == p.id)
  }))

const fullPosts = (postUrl, commentUrl) => 
  Promise .all ([axios .get (postUrl), axios .get (commentUrl)]) 
    .then (consolidate)

fullPosts (
  'https://jsonplaceholder.typicode.com/posts',
  'https://jsonplaceholder.typicode.com/comments'
) .then (console .log, console .warn)
.as-console-wrapper {max-height: 100% !important; top: 0}
<script>const axios = {get: (url) => fetch (url) .then (r => r .json ())} // dummy axios</script>

I'm one of the founders of Ramda, and a big fan, but I don't know that it offers much here.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
  • Surely your answer solves it and produces the output I was trying to get, but I think -as you mentioned- you're missing a part of the question, my intention is to solve it using pipelines or function composition as I am practicing them right now. – Ahmed Osama Nov 17 '21 at 23:17