使用 vanilla JavaScript 进行自定义数据聚合

Customized data aggregation using vanilla JavaScript

提问人:user1352042 提问时间:11/8/2023 最后编辑:user1352042 更新时间:11/10/2023 访问量:90

问:

你能帮我解决以下数据聚合问题吗?

这是我的初始数组:

const data = [
    { date: '2023-11-01', type: 'A', casualties: 10, state: 'NY', country: 'USA', site: 'hash1' },
    { date: '2023-11-01', type: 'B', casualties: 5, state: 'NY', country: 'USA', site: 'hash2' },
    { date: '2023-11-02', type: 'A', casualties: 15, state: 'NY', country: 'USA', site: 'hash3' },
    { date: '2023-11-01', type: 'C', casualties: 20, state: 'NY', country: 'USA', site: 'hash4' },
    { date: '2023-11-02', type: 'B', casualties: 8, state: 'NY', country: 'USA', site: 'hash5' },
    { date: '2023-11-03', type: 'A', casualties: 25, state: 'NY', country: 'USA', site: 'hash6' },
    { date: '2023-11-01', type: 'D', casualties: 12, state: 'NY', country: 'USA', site: 'hash7' },
];

我想根据值聚合 type 下的部分行。othercasualties

如果给定值在所有日期的阈值都等于或高于某个阈值,则它应该是数组的一部分。typecasualtiesresults

如果给定的日期都低于阈值,但它是唯一低于阈值的,则它将成为数组的一部分。typecasualtiestyperesults

如果两个或两个以上的日期都低于某个阈值, 它们不应是数组的一部分。对于此方案,将对每个日期求和,值应为 。typescasualtiesresultscasualtiestypeother

该数组应包含所有日期的阈值以下的所有内容。otherCasualtiestypescasualties

例子:

如果 是,则数组应为:casualtiesThreshold9results

results = [
    { date: '2023-11-01', type: 'A', casualties: 10, state: 'NY', country: 'USA' },
    { date: '2023-11-01', type: 'B', casualties: 5, state: 'NY', country: 'USA' },
    { date: '2023-11-02', type: 'A', casualties: 15, state: 'NY', country: 'USA' },
    { date: '2023-11-01', type: 'C', casualties: 20, state: 'NY', country: 'USA' },
    { date: '2023-11-02', type: 'B', casualties: 8, state: 'NY', country: 'USA' },
    { date: '2023-11-03', type: 'A', casualties: 25, state: 'NY', country: 'USA' },
    { date: '2023-11-01', type: 'D', casualties: 12, state: 'NY', country: 'USA' },
];

数组应为 .otherCasualties[]

如果 是,则数组应为:casualtiesThreshold13results

results = [
    { date: '2023-11-01', type: 'A', casualties: 10, state: 'NY', country: 'USA'},
    { date: '2023-11-01', type: 'other', casualties: 17, state: 'NY', country: 'USA' },
    { date: '2023-11-02', type: 'A', casualties: 15, state: 'NY', country: 'USA' },
    { date: '2023-11-01', type: 'C', casualties: 20, state: 'NY', country: 'USA' },
    { date: '2023-11-02', type: 'other', casualties: 8, state: 'NY', country: 'USA' },
    { date: '2023-11-03', type: 'A', casualties: 25, state: 'NY', country: 'USA' },
];

数组应为 .otherCasualties['B', 'D']

这是我尝试过的:

function processCasualties(data, casualtiesThreshold) {
  const results = [];
  const otherCasualties = [];

  const groupedData = data.reduce((acc, item) => {
    const key = item.type;
    if (!acc[key]) {
      acc[key] = [];
    }
    acc[key].push(item);
    return acc;
  }, {});

  const types = Object.keys(groupedData);

  types.forEach(type => {
    const typeData = groupedData[type];
    const totalCasualties = typeData.reduce((acc, item) => acc + item.casualties, 0);
    const allDatesBelowThreshold = typeData.every(item => item.casualties < casualtiesThreshold);

    if (totalCasualties >= casualtiesThreshold || (allDatesBelowThreshold && types.length === 1)) {
      results.push(...typeData.map(item => ({
        date: item.date,
        type: item.type,
        casualties: item.casualties,
        state: item.state,
        country: item.country,
      })));
    } else if (allDatesBelowThreshold) {
      otherCasualties.push(type);
    } else {
      results.push(...typeData.map(item => ({
        date: item.date,
        type: 'other',
        casualties: totalCasualties,
        state: item.state,
        country: item.country,
      })));
    }
  });

  return { results, otherCasualties };
}

const casualtiesThreshold = 13;

const { results, otherCasualties } = processCasualties(data, casualtiesThreshold);

console.log(results);
console.log(otherCasualties);

JavaScript 数组聚合

评论

0赞 user1352042 11/8/2023
嗨,妮娜 -- 谢谢你的留言。代码不起作用。我会尝试将其添加到原始问题中。
0赞 Thallius 11/8/2023
你的代码在哪里?
0赞 Nina Scholz 11/8/2023
@user1352042,您能描述一下,为什么(伤亡较小)出现在第二个结果的结果集中吗?'A'
0赞 user1352042 11/8/2023
谢谢你的问题,@NinaScholz。在第二个示例中,将 () 添加到数组中,因为在 2023-11-02 上,关联的 (15) 大于 . 并且不会添加到数组中,因为所有关联的都小于 13。如果我能够回答您的问题,请告诉我。casualtiesThreshold = 13AresultscasualtiescasualtiesThresholdBDresultscasualties
0赞 user1352042 11/8/2023
@Thallius,我已将其添加到问题中。

答:

0赞 Nina Scholz 11/9/2023 #1

您可以取两组,并在第一次迭代中收集匹配的类型和其他类型。然后删除在集合中匹配的类型,因为这些类型应位于结果集中。other

最后检查,如果集合中只有一种类型,则将此类型也添加到结果中。other

对于所有其他不匹配类型,请按 type 分组。'other'date

const
    fn = (data, threshold) => {
        const
            result = [],
            other = new Set,
            match = new Set,
            others = {};
        
        for (const { type, casualties } of data) [other, match][+(casualties >= threshold)].add(type);
        
        match.forEach(Set.prototype.delete, other);
        
        if (other.size === 1) {
            match.add(...other);
            other.clear();
        }
        
        for (const { date, type, casualties, state, country } of data) {
            if (match.has(type)) {
                result.push({ date, type, casualties, state, country });
                continue;
            }

            if (others[date]) others[date].casualties += casualties;
            else result.push(others[date] = { date, type: 'other', casualties, state, country });
        }

        return { result, otherCasualties: [...other] };
    },
    data = [{ date: '2023-11-01', type: 'A', casualties: 10, state: 'NY', country: 'USA', site: 'hash1' }, { date: '2023-11-01', type: 'B', casualties: 5, state: 'NY', country: 'USA', site: 'hash2' }, { date: '2023-11-02', type: 'A', casualties: 15, state: 'NY', country: 'USA', site: 'hash3' }, { date: '2023-11-01', type: 'C', casualties: 20, state: 'NY', country: 'USA', site: 'hash4' }, { date: '2023-11-02', type: 'B', casualties: 8, state: 'NY', country: 'USA', site: 'hash5' }, { date: '2023-11-03', type: 'A', casualties: 25, state: 'NY', country: 'USA', site: 'hash6' }, { date: '2023-11-01', type: 'D', casualties: 12, state: 'NY', country: 'USA', site: 'hash7' }];
    
console.log(fn(data, 9));
console.log(fn(data, 13));
.as-console-wrapper { max-height: 100% !important; top: 0; }

评论

0赞 user1352042 11/9/2023
感谢您解决此问题!我只需要从 for 循环中删除,使代码输出反映预期结果。site
0赞 Nina Scholz 11/9/2023
@user1352042,请参阅编辑。