![](/img/trans.png)
[英]Reduce array of objects based on “category” property and sum “amount” property
[英]groupBy/reduce an array based on sequence of the element and category
假设我有以下结构的字符串数组:
A 10
A 20
B 30
B 40
A 30
and so on...
我想根据类型(A或B)及其序列来计算平均值,因此将如下所示:
A 15
B 35
A 30
and so on...
有什么方法可以使用reduce
或类似的方法来实现上述数组?
目前,我只能想到使用循环手动遍历所有元素,并根据数据的类型和顺序手动平均它们。
我不确定这是否是一种优雅的方法,但是您可以减少并映射以获取输出。
const input = ["A:10", "A:20", "B:30", "B:40", "A:30"]; const output = input.reduce((acc,v) => { // group data based on consecutive keys const [key, value] = v.split(":"); if(acc.length && acc[acc.length - 1].key === key) { // check if last key and currenct keys are same acc[acc.length - 1].value.push(value); // push value to existing value } else { acc.push({key, value: [value]}); } return acc; }, []).map(({value, key}) => { // convert grouped array to strings using map const average = (value.reduce((a,v) => +a + +v, 0))/value.length; // find average of array of number, [10,20] will result in 15 return `${key}:${average}`; }) console.log(output);
我将其拆分为reduce和map来完成不同的任务。 第一个按键分组并记下总和和计数,第二个将其转换为所需的响应
const arr = ["A 10", "A 20", "B 30", "B 40", "A 30"]; var { answer } = arr.reduce((acc, val) => { let [type, value] = val.split(" "); if (type === acc.seq) { let currAnswer = acc.answer[acc.answer.length - 1] currAnswer.sum += Number(value); currAnswer.count++; } else { acc.answer.push({type: type, sum: Number(value), count: 1}); acc.seq = type; } return acc; }, {answer: [], seq: ''}); answer = answer.map(val => `${val.type} ${val.sum / val.count}`); console.log(answer);
编辑:我使用了两个减少,但第二个没有意义。 地图更有意义
您可以关闭最后一项,并通过始终弹出最后一个结果或不弹出最后一个结果并将中间字符串推入结果集来保持始终正确的结果。
var stringify = ({ key, sum, count }) => [key, sum / count].join(' '), array = ['A 10', 'A 20', 'B 30', 'B 40', 'A 30'], averages = array .reduce((last => (r, s) => { var [key, sum] = s.split(' '); sum *= 1; if (last.key === key) { last.sum += sum; ++last.count; } else { last = { key, sum, count: 1, index: r.push(key) - 1 }; } r[last.index] = stringify(last); return r; })({}), []); console.log(averages);
您可以使用array#reduce
并比较当前值和先前值,当它们不同时,取该值的平均值并将其推入数组。
let arr = ['A 10', 'A 20', 'B 30', 'B 40', 'A 30', 'A 10', 'A 40'], sum = 0, length = 0; result = arr.reduce((r, s, i, a) => { let [key, value] = s.split(/\\s+/); let [lastKey, lastValue] = (a[i-1] || '').split(/\\s+/); if(lastKey && key !== lastKey) { r.push(`${lastKey} ${sum/length}`); sum = +value; length = 1; } else { sum += +value; length += 1; } if(i === a.length - 1) { r.push(`${key} ${sum/length}`); } return r; }, []); console.log(result);
干得好
arr = ["A: 10", "A: 20", "B: 30", "B: 40", "A: 31"];
let outObj = arr.reduce((acc, item) => {
let [key, value] = item.split(/[\ :]+/);
value = parseInt(value);
if (key in acc) {
acc[key][0]++;
acc[key][1] += value;
} else {
acc[key] = [1, value];
}
return acc;
}, {});
for (key in outObj) {
console.log(key, ":", outObj[key][1] / outObj[key][0]);
}
const input = ["A:10", "A:20", "B:30", "B:40", "A:30"]; function groupBy(els) { let keys = []; let values = []; input.forEach((el) => { const [key, value] = el.split(":"); if (keys[keys.length - 1] !== key) { keys[keys.length] = key; values[keys.length - 1] = [parseInt(value)]; } else { values[keys.length - 1].push(parseInt(value)) } }); return keys.map((el, index) => [el, values[index].reduce((acc, el) => acc + el, 0) / values[index].length]) } console.log(groupBy(input))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.