Javascript 更好地使用对象列表的转换,而不是使用2个减缩器

Javascript 更好地使用对象列表的转换,而不是使用2个减缩器,javascript,arrays,loops,functional-programming,reduce,Javascript,Arrays,Loops,Functional Programming,Reduce,考虑以下对象列表: const blogs = [ { title: "React patterns", author: "Michael Chan", url: "https://reactpatterns.com/", likes: 7, }, { title: "Go To Statement Considered Harmful", author: "Edsger W. Dijkstra",

考虑以下对象列表:

const blogs = [
    {
      title: "React patterns",
      author: "Michael Chan",
      url: "https://reactpatterns.com/",
      likes: 7,
    },
    {
      title: "Go To Statement Considered Harmful",
      author: "Edsger W. Dijkstra",
      likes: 5,
    },
    {
      title: "Canonical string reduction",
      author: "Edsger W. Dijkstra",
      likes: 12,
    },
    {
      title: "First class tests",
      author: "Robert C. Martin",
      likes: 10,
    },
    {
      title: "TDD harms architecture",
      author: "Robert C. Martin",
      likes: 0,
    },
    {
      title: "Type wars",
      author: "Robert C. Martin",
      likes: 2,
    }  
]
我需要做的是,编写一个函数,返回blog对象,作者拥有他写的最多的blog,格式如下(这也是本例中的预期结果):

这是我提出的第一个解决方案,涉及2个减速机

const mostBlogs = blogs => {
    const formatted_blogs = blogs.reduce((acc, cur_blog)=>{
        if (!acc[cur_blog.author]){
            acc[cur_blog.author] = {
                author: cur_blog.author, blogs: 1
            }
        } else {
            acc[cur_blog.author].blogs++;
        }
        return acc;
    }, {});

    return Object.keys(formatted_blogs).reduce((acc, cur)=>{
        if (formatted_blogs[cur].blogs > (acc.blogs||0))
            return ( {...formatted_blogs[cur]} )
        return acc;
    }, {});
}
我想知道如何才能使它更好,只使用一个减速机,这将是更有效和更智能。当我在这里输入问题时,我实际上想出了另一个只使用1个减速机的解决方案。我很想听听你对它的看法,这能优化吗?它足够聪明/高效吗?或者我可以在这里做些不同的事情,这会是一个更好的练习吗

const mostBlogs = blogs => {
    const { most_blogs } = blogs.reduce((acc, cur_blog)=>{
        // if author doesn't exist in acc.all, add a new formatted obj
        if (!acc.all[cur_blog.author])
            acc.all[cur_blog.author] = { author: cur_blog.author, blogs: 1 };
        // if exists, simply increment the blogs prop count in acc.all
        else 
            acc.all[cur_blog.author].blogs++;

        // check if cur_blog blogs prop in acc.all is higher than
        // existing one in acc.most_blogs blogs prop, overwrite obj if so
        if (acc.all[cur_blog.author].blogs > (acc.most_blogs.blogs||0))
            acc.most_blogs = acc.all[cur_blog.author];

        return acc;
    }, {all: {}, most_blogs: {} });

    return most_blogs;
}

您可以使用一个数组进行单个循环,以获得最高计数

const
博客=[{标题:“反应模式”,作者:“Michael Chan”,url:https://reactpatterns.com/“,likes:7},{标题:“转到被认为有害的语句”,作者:“Edsger W.Dijkstra”,作者:5},{标题:“规范字符串缩减”,作者:“Edsger W.Dijkstra”,作者:12},{标题:“第一类测试”,作者:“Robert C.Martin”,作者:10},{标题:“TDD危害体系结构”,作者:“Robert C.Martin”,喜欢:0},{标题:“类型战争”,作者:“Robert C.Martin”,喜欢:2},
mostBlogs=blogs=>blogs
.reduce((acc,{author})=>{
var top=acc.top.length&&acc.top[0]。博客;
如果(!acc.authors[author])acc.authors[author]={作者,博客:0};
如果(top<++acc.authors[author].blogs)acc.top=[acc.authors[author]];
如果(top==acc.authors[author].blogs)acc.top.push(acc.authors[author]);
返回acc;
},{作者:{},顶部:[]})
顶部

console.log(mostBlogs(blogs));
可以使用
reduce
方法对
title
进行计数,然后按标题对其进行排序:

const grouped = Object.values(blogs.reduce((a, {author, title}) => {
    a[author] = a[author] || {author, blogs: 0};
    a[author].blogs += 1;
    return a;
}, {}));


grouped.sort((a, b) => b.blogs - a.blogs)[0];
我的灵感来自(感谢您展示了在reduce方法中使用累加器的如此好的方式)。在我看来,Nina的答案是最好的,应该被标记为答案。也许这是Nina答案的一个稍微重构的版本,但是,在我看来,答案应该发布。所以这个版本具有
O(1)
复杂性:

const grouped = blogs.reduce((a, { author }) => {
    a[author] = a[author] || {author, blogs: 0};
    a[author].blogs += 1;
    if (a.topAuthor.hasOwnProperty('blogs') && a[author].blogs >  a.topAuthor.blogs)
        a.topAuthor = a[author];
    else if (Object.keys(a.topAuthor) == 0)
        a.topAuthor = a[author];
    return a;
}, {author: {}, topAuthor: {}});

console.log(grouped.topAuthor);
例如:

const博客=[
{
标题:“反应模式”,作者:“Michael Chan”,
url:“https://reactpatterns.com/,喜欢:7,
},
{
标题:“发表被认为有害的声明”,作者:“Edsger W.Dijkstra”,
喜欢:5,
},
{
标题:“规范字符串缩减”,作者:“Edsger W.Dijkstra”,
喜欢:12,
},
{
标题:“一级考试”,作者:“罗伯特·C·马丁”,
喜欢:10,
},
{
标题:“TDD危害建筑”,作者:“Robert C.Martin”,喜欢:0,
},
{
标题:“类型战争”,作者:“罗伯特·C·马丁”,喜欢:2,
}
];
const group=blogs.reduce((a,{author})=>{
a[作者]=a[作者]|{作者,博客:0};
a[作者]。博客+=1;
if(a.topAuthor.hasOwnProperty('blogs')&&a[author].blogs>a.topAuthor.blogs)
a、 topAuthor=一位[作者];
else if(Object.keys(a.topAuthor)==0)
a、 topAuthor=一位[作者];
返回a;
},{作者:{},顶级作者:{});

console.log(grouped.topAuthor);
如果您准备使用额外的8KB库(免责声明…它是我的),您可以使用。它使这类事情变得简单易读:

import { blinq } from "blinq";
//...
const v = blinq(blogs)
  .groupBy(blog => blog.author)
  .select(grp => ({ author: grp.key, blogs: grp.count() }))
  .maxBy(o => o.blogs) //returns a sequence... there might be several maximums
  .first();
const{
布林克
}=window.blinq
常量博客=[{
标题:“反应模式”,
作者:“Michael Chan”,
url:“https://reactpatterns.com/",
喜欢:7
},
{
标题:“转到被认为有害的声明”,
作者:“Edsger W.Dijkstra”,
喜欢:5
},
{
标题:“规范字符串缩减”,
作者:“Edsger W.Dijkstra”,
喜欢:12
},
{
标题:“一流测试”,
作者:“罗伯特·C·马丁”,
喜欢:10
},
{
标题:“TDD危害建筑”,
作者:“罗伯特·C·马丁”,
喜欢:0
},
{
标题:“类型战争”,
作者:“罗伯特·C·马丁”,
喜欢:2
}
];
const v=blinq(博客)
.groupBy(blog=>blog.author)
.选择(grp=>({
作者:grp.key,
blogs:grp.count()
}))
.maxBy(o=>o.blogs)//返回一个序列…可能有几个最大值
.first();
console.log(v);

这里有一个使用vanilla JS的简单解决方案

const输入=[{
标题:“反应模式”,
作者:“Michael Chan”,
url:“https://reactpatterns.com/",
喜欢:7,
},
{
标题:“转到被认为有害的声明”,
作者:“Edsger W.Dijkstra”,
喜欢:5,
},
{
标题:“规范字符串缩减”,
作者:“Edsger W.Dijkstra”,
喜欢:12,
},
{
标题:“一流测试”,
作者:“罗伯特·C·马丁”,
喜欢:10,
},
{
标题:“TDD危害建筑”,
作者:“罗伯特·C·马丁”,
喜欢:0,
},
{
标题:“类型战争”,
作者:“罗伯特·C·马丁”,
喜欢:2,,
}
]
constTopBloggers=input.reduce((o,{author})=>
({…o[作者]:o[作者]?o[作者]+1:1}),{})
const[[author,blogs]]=Object.entries(topBloggers)
.sort(([,countA],,countB])=>countB-countA)
const topBlogger={作者,博客}

console.log(topBlogger)
这就是我要做的

constblogs=[{“title”:“React patterns”,“author”:“Michael Chan”,“url”:https://reactpatterns.com/“,”likes“:7},{”title“:”转到被认为有害的语句“,”作者“:”Edsger W.Dijkstra“,”likes“:”5},{”title“,”规范字符串缩减“,”作者“,”Edsger W.Dijkstra“,”likes“:”12},{”title“:”一级测试“,”作者“:”Robert C.Martin“,”likes”:10},{“标题”:“TDD危害建筑”,“作者”:“罗伯特·C·马丁”,“喜欢”:0},{“标题”:“类型战争”,“作者”:“罗伯特·C·马丁”,“喜欢”:2});
const reducer=({mode,histogram},{author})=>{
常量{[作者]:频率=0}=直方图;
import { blinq } from "blinq";
//...
const v = blinq(blogs)
  .groupBy(blog => blog.author)
  .select(grp => ({ author: grp.key, blogs: grp.count() }))
  .maxBy(o => o.blogs) //returns a sequence... there might be several maximums
  .first();