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>