【问题标题】:lodash sum object's values if key meets requirements如果键满足要求,lodash 和对象的值
【发布时间】:2019-10-06 13:48:00
【问题描述】:

我在服务中有一个 observable,当订阅它时,它会返回一个对象,其中记录了用户为他从事的每个项目记录的时间。

 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 记录的小时数进行分组

【问题讨论】:

  • 所以基本上你需要按 id 分组?
  • 对具有相同 id 的项目的小时数进行分组和求和(项目的 id 必须在 currentUserIds 中遇到 - 否则小时数总和应在“未定义”id 下)。

标签: javascript angular typescript oop lodash


【解决方案1】:

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

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>

还有更简洁的 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>

【讨论】:

  • 我还没有机会看sn-p,但是为什么未指定有61?
  • 检查数据。
猜你喜欢
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 2016-12-11
  • 2017-11-27
  • 2019-05-11
相关资源
最近更新 更多