Javascript Lodash代码优化/重构

Javascript Lodash代码优化/重构,javascript,json,lodash,Javascript,Json,Lodash,这是原始JSON数据: var data= [ { project: "ABC", area: 'Test', subArea: 'Dev', done: 10 }, { project: "ABC", area: 'Test', subArea: 'QA', done: 10 }, { project: "ABC", area: 'Test', subArea: 'Support', d

这是原始JSON数据:

var data= [
      { project: "ABC",    area: 'Test',       subArea: 'Dev',     done: 10 },
      { project: "ABC",    area: 'Test',       subArea: 'QA',      done: 10 },
      { project: "ABC",    area: 'Test',       subArea: 'Support', done: 10 },
      { project: "ABC",    area: 'External',   subArea: 'Dev',     done: 5  },
      { project: "ABC",    area: 'External',   subArea: 'QA',      done: 5  },
      { project: "ABC",    area: 'External',   subArea: 'Support', done: 5  },
      { project: "ABC",    area: 'Escalation', subArea: 'Dev',     done: 20 },
      { project: "ABC",    area: 'Escalation', subArea: 'QA',      done: 20 },
      { project: "ABC",    area: 'Escalation', subArea: 'Support', done: 20 },
      { project: "ABC123", area: 'Test',       subArea: 'Dev',     done: 20 },
      { project: "ABC123", area: 'Test',       subArea: 'QA',      done: 20 },
      { project: "ABC123", area: 'Test',       subArea: 'Support', done: 20 },
      { project: "ABC123", area: 'External',   subArea: 'Dev',     done: 10 },
      { project: "ABC123", area: 'External',   subArea: 'QA',      done: 10 },
      { project: "ABC123", area: 'External',   subArea: 'Support', done: 10 },
      { project: "ABC123", area: 'Escalation', subArea: 'Dev',     done: 5  },
      { project: "ABC123", area: 'Escalation', subArea: 'QA',      done: 5  },
      { project: "ABC123", area: 'Escalation', subArea: 'Support', done: 5  },
    ];
我需要的是按项目对项目进行分组,将它们划分为区域,并对每个子区域的完成时间进行汇总。新的JSON结果必须如下所示:

    [
   {
      "name": "ABC",
      "test": {
         "total": 30,
         "totalDev": 10,
         "totalQA": 10,
         "totalSup": 10
      },
      "external": {
         "total": 15,
         "totalDev": 5,
         "totalQA": 5,
         "totalSup": 5
      },
      "escalation": {
         "total": 60,
         "totalDev": 20,
         "totalQA": 20,
         "totalSup": 20
      }
   },
   {
      "name": "ABC123",
      "test": {
         "total": 60,
         "totalDev": 20,
         "totalQA": 20,
         "totalSup": 20
      },
      "external": {
         "total": 30,
         "totalDev": 10,
         "totalQA": 10,
         "totalSup": 10
      },
      "escalation": {
         "total": 15,
         "totalDev": 5,
         "totalQA": 5,
         "totalSup": 5
      }
   }
]
_.reduce(_.filter(projectGroup, ...), sum, 0)
下面是我的实际代码,我已经得到了我想要的结果,但我认为代码可以更优化。无需重复和所有条件验证,无需硬编码映射块内的区域和子区域属性,因为这些值在服务器端是动态区域

var sum = (total, item) => total += item.done;

result = _.chain(data)
          .groupBy(function(value) { return value.project })
          .map((projectGroup, projectName) => ({ 
                  name: projectName,
                  test: {
                      total:    _.reduce(_.filter(projectGroup, (o) => ( o.area === 'Test')) , sum, 0),
                      totalDev: _.reduce(_.filter(projectGroup, (o) => ( o.area === 'Test' && o.subArea === 'Dev')) , sum, 0),
                      totalQA:  _.reduce(_.filter(projectGroup, (o) => ( o.area === 'Test' && o.subArea === 'QA')) , sum, 0),
                      totalSup: _.reduce(_.filter(projectGroup, (o) => ( o.area === 'Test' && o.subArea === 'Support')) , sum, 0)
                  },
                 external: {
                      total:    _.reduce(_.filter(projectGroup, (o) => ( o.area === 'External')) , sum, 0),
                      totalDev: _.reduce(_.filter(projectGroup, (o) => ( o.area === 'External' && o.subArea === 'Dev')) , sum, 0),
                      totalQA:  _.reduce(_.filter(projectGroup, (o) => ( o.area === 'External' && o.subArea === 'QA')) , sum, 0),
                      totalSup: _.reduce(_.filter(projectGroup, (o) => ( o.area === 'External' && o.subArea === 'Support')) , sum, 0)
                  },
                  escalation: {
                      total:    _.reduce(_.filter(projectGroup, (o) => ( o.area === 'Escalation')) , sum, 0),
                      totalDev: _.reduce(_.filter(projectGroup, (o) => ( o.area === 'Escalation' && o.subArea === 'Dev')) , sum, 0),
                      totalQA:  _.reduce(_.filter(projectGroup, (o) => ( o.area === 'Escalation' && o.subArea === 'QA')) , sum, 0),
                      totalSup: _.reduce(_.filter(projectGroup, (o) => ( o.area === 'Escalation' && o.subArea === 'Support')) , sum, 0)
                  }       
    }))

我不知道你想在这里优化什么,lodash应该代替你来做。我只有一句话

var sum = (total, item) => total += item.done;
function reduceData(projectGroup, projectName, comparationLabel) {
   return {
     total:    _.reduce(_.filter(projectGroup, (o) => ( o.area === comparationLabel)) , sum, 0),
     totalDev: _.reduce(_.filter(projectGroup, (o) => ( o.area === comparationLabel && o.subArea === 'Dev')) , sum, 0),
     totalQA:  _.reduce(_.filter(projectGroup, (o) => ( o.area === comparationLabel && o.subArea === 'QA')) , sum, 0),
     totalSup: _.reduce(_.filter(projectGroup, (o) => ( o.area === comparationLabel && o.subArea === 'Support')) , sum, 0)
   }
}
result = _.chain(data)
          .groupBy(function(value) { return value.project })
          .map((projectGroup, projectName) => ({ 
                  name: projectName,
                  test: reduceData(projectGroup, projectName, 'Test'),
                  external: reduceData(projectGroup, projectName, 'External'),
                  escalation: reduceData(projectGroup, projectName, 'Escalation')    
    }))

是的,如果要进行某种缓存,可以避免使用
.filter(projectGroup,(o)
,但这样可以节省少量的程序资源。

而不是像这样嵌套:

    [
   {
      "name": "ABC",
      "test": {
         "total": 30,
         "totalDev": 10,
         "totalQA": 10,
         "totalSup": 10
      },
      "external": {
         "total": 15,
         "totalDev": 5,
         "totalQA": 5,
         "totalSup": 5
      },
      "escalation": {
         "total": 60,
         "totalDev": 20,
         "totalQA": 20,
         "totalSup": 20
      }
   },
   {
      "name": "ABC123",
      "test": {
         "total": 60,
         "totalDev": 20,
         "totalQA": 20,
         "totalSup": 20
      },
      "external": {
         "total": 30,
         "totalDev": 10,
         "totalQA": 10,
         "totalSup": 10
      },
      "escalation": {
         "total": 15,
         "totalDev": 5,
         "totalQA": 5,
         "totalSup": 5
      }
   }
]
_.reduce(_.filter(projectGroup, ...), sum, 0)
可以这样做以防止在集合上循环两次:

_(projectGroup).filter(...).reduce(sum, 0).value()

为什么不在普通Javascript中使用单个循环来分组和汇总小时数

此提案使用哈希表,并按
project
属性的值进行分组

var data=[{project:'ABC',area:'Test',subArea:'Dev',done:10},{project:'ABC',area:'Test',subArea:'Support',done:10},{project:'ABC',area:'Dev',done:5},{project:'ABC',area ternal QA',done:5},{project:'ABC',区域:'外部',分区:'支持',完成:5},{project:'ABC',区域:'升级',分区:'开发',完成:20},{project:'ABC',区域:'升级',分区:'QA',完成:20},{project:'ABC',区域:'升级',分区:'支持',完成:20},{project:'ABC123',区域:'测试',分区:'开发',完成:20},{project:'ABC123',区域:'Test',分区:'QA',完成时间:20},{project:'ABC123',区域:'Support',完成时间:20},{project:'ABC123',区域:'External',分区:'Dev',完成时间:10},{project:'ABC123',分区:'Support',完成时间:10},{project:'ABC123',分区:'Support,区域:'Escalation',子区域:'Dev',done:5},{project:'ABC123',区域:'Escalation',子区域:'QA',done:5},{project:'ABC123',区域:'Escalation',子区域:'Support',done:5},
结果=[];
data.forEach(函数(a){
var area=a.area.toLowerCase(),
分区=‘总计’+a.分区;
如果(!此[a.项目]){
此[a.project]={name:a.project};
结果推送(这个[一个项目]);
}
此[a.project][area]=此[a.project][area]|{总计:0};
此[a.项目][区域][分区]=(此[a.项目][区域][分区]| | 0)+a.完成;
此[a.项目][区域].total+=a.完成;
},Object.create(null));
console.log(结果);

.as控制台包装{max height:100%!important;top:0;}
.groupBy(函数(值){return value.project})
可以是
.groupBy('project'))
为什么abc test totaldev=30?数字来自哪里?我编辑了,现在它是正确的。谢谢!这就是我要找的!谢谢!你的代码非常好,解决了我的问题,但我现在觉得使用Lodash更舒服。谢谢!我会做出更改。