如果键满足要求,lodash将对象的值相加

时间:2019-05-20 08:10:44

标签: javascript angular typescript oop lodash

我在服务内部有一个可观察的对象,当订阅该服务时,该对象将返回一个对象,该对象的用户工作时间记录在他从事的每个项目中。

 this.calculationService.getSumsByProject().subscribe(sum =>
   console.log(sum);
}

该日志显示类似{undefined: 0, MISSING!: 16, Project1: 5, Project2:1, Project3: 20,Project4: 15}

的数据

项目是Project类型数组的一部分,看起来像这样:

projects: Project[] = [
{name: 'MISSING',ids:[]},
{name: 'Project1', ids:['pid75.22','pid75.23']},
{name: 'Project2', ids:['pid75.22','pid75.23']},
{name: 'Project3', ids:['pid66.1','pid33.99']},
{name: 'Project4', ids:['pdi75.88','pid99.15']}]

我有一个数组,其用户ID如下:

currentUserIds=['pid75.22','pid100.03','pid75.88','Not Specified']

我想做什么:

我的目标是解析对象的键-值对并添加记录在用户ID下的小时数。未指定将获取与用户没有通用ID的项目的小时数。

例如:

pid75.22:6
pid100.03:0
pid75.88:15
Not specified:36

到目前为止,我所做的事情以及卡住的地方

loggedProjectNames: string[];

loggedProjectHours: string[];

projectByName(name: string): Project {
        return _.find(this.projects, { name }) || this.projects[0];
  }

ngOnInit() {
    this.calculationService.getSumsByProject().subscribe(sum => {
      //console.log(sum);
      this.loggedProjectNames = _.keys(sum);
      this.loggedProjectHours = _.values(sum);
      //console.log(this.loggedProjectNames,": ",this.loggedProjectHours);
      this.loggedProjectNames.forEach(name => {
        const found = this.projectByName(name);
        this.currentUserIds.forEach(id => {
           console.log(_.find(found.ids, i => i === id));
        })
      })
    });

如何从这里开始?现在我检索了与密钥相关的项目,因此我不确定如何对公用ID记录的小时数进行分组

1 个答案:

答案 0 :(得分:0)

您可以使用lodash _.flow()创建一个进行转换的函数(请参见代码中的注释)。

const { flow, flatMap, map, partialRight: pr, groupBy, head, mapValues, zipObject, constant, times, size, sumBy, last, over, pick, omit, values, sum, spread, merge, partial } = _

const hoursByProject = {undefined: 0, 'MISSING!': 16, Project1: 5, Project2:1, Project3: 20,Project4: 15}

const createDefaults = userIds => zipObject(userIds, times(size(userIds), constant(0)))

const projectsBId = userIds => flow(
  pr(flatMap, ({ name, ids }) => map(ids, id => [id, hoursByProject[name]])), // convert from project-ids to id-> project
  pr(groupBy, head), // group all instance of id
  pr(mapValues, g => sumBy(g, last)), // sum the hours for each id
  over([
    pr(pick, userIds), // get the values for the list of ids
    flow(pr(omit, userIds), values, sum, s => ({ 'Not Specified': s })) // some the values for the others
  ]),
  spread(partial(merge, createDefaults(userIds))) // merge to a single object with defaults of 0 for missing ids
) 

const projects = [{"name":"MISSING","ids":[]},{"name":"Project1","ids":["pid75.22","pid75.23"]},{"name":"Project2","ids":["pid75.22","pid75.23"]},{"name":"Project3","ids":["pid66.1","pid33.99"]},{"name":"Project4","ids":["pid75.88","pid99.15"]}]

const currentUserIds = ['pid75.22','pid100.03','pid75.88','Not Specified']

const result = projectsBId(currentUserIds)(projects)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

以及terser lodash / fp版本:

const { flow, flatMap, map, groupBy, head, mapValues, sumBy, last, over, defaults, pick, omit, values, sum, mergeAll, zipObject, times, size, constant } = _

const hoursByProject = {undefined: 0, 'MISSING!': 16, Project1: 5, Project2:1, Project3: 20,Project4: 15}

const createDefaults = userIds => zipObject(userIds, times(constant(0), size(userIds)))

const projectsBId = userIds => flow(
  flatMap(({ name, ids }) => map(id => [id, hoursByProject[name]], ids)), // convert from project + ids to id + hours
  groupBy(head), // group all instance of id
  mapValues(sumBy(last)), // sum the hours for each id
  defaults(createDefaults(userIds)), // add default 0 values for all user ids
  over([
    pick(userIds), // get the values for the list of ids
    flow(omit(userIds), values, sum, s => ({ 'Not Specified': s })) // some the values for the others
  ]),
  mergeAll // merge to a single object
) 

const projects = [{"name":"MISSING","ids":[]},{"name":"Project1","ids":["pid75.22","pid75.23"]},{"name":"Project2","ids":["pid75.22","pid75.23"]},{"name":"Project3","ids":["pid66.1","pid33.99"]},{"name":"Project4","ids":["pid75.88","pid99.15"]}]

const currentUserIds = ['pid75.22','pid100.03','pid75.88','Not Specified']

const result = projectsBId(currentUserIds)(projects)

console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>