Home > front end >  Is there a better way to refactor this function using the Lodash library?
Is there a better way to refactor this function using the Lodash library?

Time:05-15

My goal was to take a list of blogs and find the author with the most blogs returning an object like this { author: String, blogs: Number }. I was successful, but I want to know a better approach to my solution using Lodash. Thank You!

let blogs = [
    { title: 'sorceror stone', author: 'rowling', likes: 5 },
    { title: 'prisoner of azkaban', author: 'rowling', likes: 13 },
    { title: 'green mile', author: 'king', likes: 3 },
    { title: 'oliver twist', author: 'dickens', likes: 7 },
    { title: 'the half blood prince', author: 'rowling', likes: 16 },
    { title: 'david copperfield', author: 'dickens', likes: 10 },
    { title: 'christmas carol', author: 'dickens', likes: 3 },
    { title: 'tale of two cities', author: 'dickens', likes: 20 },
]

const mostBlogs = (blogs) => {
    let authorsByBlogs = _.countBy(blogs, 'author')

    let maxBlogs = _.max(_.values(authorsByBlogs))

    let author = _.findKey(authorsByBlogs, (o) => {
        return o === maxBlogs
    })

    return { author: author, blogs: maxBlogs }
}

console.log(mostBlogs(blogs)) // { author: "dickens", blogs: 4}

CodePudding user response:

This is a refactor of your function using lodash's _.flow() (see comments in code):

const { flow, countBy, toPairs, maxBy, last, zipObject } = _

const mostBlogs = flow(
  blogs => countBy(blogs, 'author'), // count by the author
  toPairs, // convert to array of [key, value] pairs
  blogs => maxBy(blogs, last), // get the entry with most blogs
  blog => zipObject(['author', 'blogs'], blog) // convert to an object
)

const blogs = [{"title":"sorceror stone","author":"rowling","likes":5},{"title":"prisoner of azkaban","author":"rowling","likes":13},{"title":"green mile","author":"king","likes":3},{"title":"oliver twist","author":"dickens","likes":7},{"title":"the half blood prince","author":"rowling","likes":16},{"title":"david copperfield","author":"dickens","likes":10},{"title":"christmas carol","author":"dickens","likes":3},{"title":"tale of two cities","author":"dickens","likes":20}]

const result = mostBlogs(blogs)

console.log(result) // { author: "dickens", blogs: 4}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG ljU96qKRCWh quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

And the same idea using lodash/fp:

const { flow, countBy, toPairs, maxBy, last, zipObject } = _

const mostBlogs = flow(
  countBy('author'), // count by the author
  toPairs, // convert to array of [key, value] pairs
  maxBy(last), // get the entry with most blogs
  zipObject(['author', 'blogs']) // convert to an object
)

const blogs = [{"title":"sorceror stone","author":"rowling","likes":5},{"title":"prisoner of azkaban","author":"rowling","likes":13},{"title":"green mile","author":"king","likes":3},{"title":"oliver twist","author":"dickens","likes":7},{"title":"the half blood prince","author":"rowling","likes":16},{"title":"david copperfield","author":"dickens","likes":10},{"title":"christmas carol","author":"dickens","likes":3},{"title":"tale of two cities","author":"dickens","likes":20}]

const result = mostBlogs(blogs)

console.log(result) // { author: "dickens", blogs: 4}
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js lodash.fp.min.js)'></script>

  • Related