group /根据元素和类别的顺序减少/减少数组

时间:2018-12-27 13:19:58

标签: javascript

假设我有一个具有以下结构的字符串数组:

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或类似的方法来实现上面的数组?

目前,我只能想到使用循环手动遍历所有元素并根据数据的类型和顺序对它们进行平均。

6 个答案:

答案 0 :(得分:2)

我不确定这是否是一种优雅的方式,但是您可以进行缩小和映射以获取输出。

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

答案 1 :(得分:1)

我将其拆分为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);

编辑:我使用了两次减少,但是第二次没有任何意义。地图更有意义

答案 2 :(得分:1)

您可以关闭最后一个项目,并通过不弹出最后一个结果并将中间字符串推入结果集来保持始终正确的结果。

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

答案 3 :(得分:1)

您可以使用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);

答案 4 :(得分:0)

你在这里

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

答案 5 :(得分: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))