代码之家  ›  专栏  ›  技术社区  ›  Bla...

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

  •  0
  • Bla...  · 技术社区  · 5 年前

    假设我有一个字符串数组,其结构如下:

    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 回复  |  直到 5 年前
        1
  •  2
  •   Amit Chauhan    5 年前

    我不确定这是不是优雅的方式,但你可以做减少和地图得到你的产出。

    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);
        2
  •  1
  •   iagowp    5 年前

    我把它分成了一个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);

    编辑:我用了两个减法,但第二个没有意义。地图更有意义

        3
  •  1
  •   Nina Scholz    5 年前

    您可以对最后一个项进行闭包,并通过弹出或不弹出最后一个结果并将中间字符串推送到结果集来维护始终正确的结果。

    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);
        4
  •  1
  •   Hassan Imam Ravi kant    5 年前

    你可以用 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);
        5
  •  0
  •   Sumer    5 年前

    干得好

    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]);
    }
    
        6
  •  0
  •   Vadim Hulevich    5 年前

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