значения объекта lodash sum, если ключ соответствует требованиям - PullRequest
0 голосов
/ 20 мая 2019

У меня есть наблюдаемая внутри службы, которая при подписке возвращает объект с часами пользователя, зарегистрированными для каждого проекта, над которым он работал.

 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']}]

У меня есть массив идентификаторов пользователя, например:

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

Что я хочу сделать:

Моя цель состоит в том, чтобы проанализировать пары ключ-значение объекта и добавить часы, зарегистрированные под идентификаторами пользователя. Не указано, получает часы от проектов, которые не имеют общих идентификаторов с пользователем.

Например:

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));
        })
      })
    });

Как мне идти дальше? Теперь, когда я получил проекты, связанные с ключом, я не уверен, как сгруппировать часы, зарегистрированные по общему идентификатору

1 Ответ

0 голосов
/ 20 мая 2019

Вы можете создать функцию с 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>

И более краткая версия 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>
...