简体   繁体   English

功能性 Javascript 映射/减少准备报告数据

[英]Functional Javascript map/reduce in preparing report data

I am struggling to understand how to properly employ Array.reduce() to assemble summary/report data (ie, grouped counts).我正在努力理解如何正确使用Array.reduce()来组合汇总/报告数据(即分组计数)。 I typically do this manually by looping over the data with forEach and building up the object, but I feel like chaining map and reduce has got to be a more elegant, functional way of doing it;我通常通过使用forEach循环数据并构建对象来手动执行此操作,但我觉得链接 map 和 reduce 必须是一种更优雅、更实用的方法; I'm just failing to figure out how to do this correctly.我只是不知道如何正确地做到这一点。

Here is where my experimentation has gotten me:这是我的实验让我受益的地方:

const articleData = [
    {newsSource: "AP", title: "Some article.", category: "World"},
    {newsSource: "BBC", title: "Some article.", category: "Politics"},
    {newsSource: "CBS", title: "Some article.", category: "Sports"},
    {newsSource: "CNN", title: "Some article.", category: "Finance"},
    {newsSource: "CNN", title: "Another article.", category: "Politics"},
    {newsSource: "NBC", title: "Some article.", category: "Politics"},
    {newsSource: "NBC", title: "Another article.", category: "Finance"},
    {newsSource: "Reuters", title: "Some article.", category: "World"},
    {newsSource: "Reuters", title: "Another article.", category: "Politics"},
    {newsSource: "Reuters", title: "Yet another article.", category: "Finance"}
];

// I want to set reportData to be the result of the chained map/reduce
// ...not declare it here and assemble it within the functions below
let reportData = {};

articleData.map((item, index) => {
    if (item.newsSource) return item.newsSource;
})
.reduce((acc, newsSource) => {

    if (!reportData[newsSource]) {
        reportData[newsSource] = 1;
    } else {
        reportData[newsSource] = reportData[newsSource] + 1;
    }

    return (acc, reportData);

});

console.log(reportData);
// Expected output:
// { AP: 1, BBC: 1, CBS: 1, CNN: 2, NBC: 2, Reuters: 3 }

There are a number of problems here.这里有很多问题。 (Not the least of which is that it skips the first data element! I think I understand why, but I don't know how to fix it.) But most importantly, I want to understand how to construct my reduce function so I'm not altering reportData within it, rather I'm returning the properly structured data shown under "Expected output". (其中最重要的是它跳过了第一个数据元素!我想我明白为什么,但我不知道如何修复它。)但最重要的是,我想了解如何构建我的reduce函数,所以我'我没有更改其中的reportData ,而是返回“预期输出”下显示的正确结构化数据。

Reducing a flat array is clear to me, but I get confused once I'm dealing with a structure of any depth beyond that.减少平面阵列对我来说很清楚,但是一旦我处理超出该深度的任何结构,我就会感到困惑。

You can just use Array.reduce directly on articleData :您可以直接在articleData上使用Array.reduce

reportData = articleData.reduce(function(c, a) {
  c[a.newsSource] = (c[a.newsSource] || 0) + 1;
  return c;
}, {});

console.log(reportData);

Note that as @CertainPerformance pointed out in their comment, you need to pass an initial value to reduce otherwise the first value in the array is used as the initial value and not included in the iteration.请注意,正如@CertainPerformance 在他们的评论中指出的那样,您需要传递一个初始值来reduce否则数组中的第一个值将用作初始值并且不包含在迭代中。

 const articleData = [{ newsSource: "AP", title: "Some article.", category: "World" }, { newsSource: "BBC", title: "Some article.", category: "Politics" }, { newsSource: "CBS", title: "Some article.", category: "Sports" }, { newsSource: "CNN", title: "Some article.", category: "Finance" }, { newsSource: "CNN", title: "Another article.", category: "Politics" }, { newsSource: "NBC", title: "Some article.", category: "Politics" }, { newsSource: "NBC", title: "Another article.", category: "Finance" }, { newsSource: "Reuters", title: "Some article.", category: "World" }, { newsSource: "Reuters", title: "Another article.", category: "Politics" }, { newsSource: "Reuters", title: "Yet another article.", category: "Finance" } ]; reportData = articleData.reduce(function(c, a) { c[a.newsSource] = (c[a.newsSource] || 0) + 1; return c; }, {}); console.log(reportData);

You can pass fist value to accumulate in 2nd param of reduce method.您可以通过第一个值在reduce方法的2nd param中进行累加。 You can skip value or manipulate the value in callback function.您可以在callback函数中跳过值或manipulate值。

 const articleData = [ { newsSource: "AP", title: "Some article.", category: "World" }, { newsSource: "BBC", title: "Some article.", category: "Politics" }, { newsSource: "CBS", title: "Some article.", category: "Sports" }, { newsSource: "CNN", title: "Some article.", category: "Finance" }, { newsSource: "CNN", title: "Another article.", category: "Politics" }, { newsSource: "NBC", title: "Some article.", category: "Politics" }, { newsSource: "NBC", title: "Another article.", category: "Finance" }, { newsSource: "Reuters", title: "Some article.", category: "World" }, { newsSource: "Reuters", title: "Another article.", category: "Politics" }, { newsSource: "Reuters", title: "Yet another article.", category: "Finance" } ]; const reportData = articleData.reduce((acc, { newsSource }) => { if (!acc[newsSource]) acc[newsSource] = 0; acc[newsSource] += 1; return acc; }, {}); console.log(reportData);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM