Суммируйте каждые 5 значений массива объектов - PullRequest
0 голосов
/ 08 октября 2019

Скажем, у меня есть массив объектов неопределенной длины, подобный этому

jString = [
  {
    "value": "2,335.47"
  },
  {
    "value": "2,862.96"
  },
  {
    "value": "2,217.31"
  },
  {
    "value": "1,627.01"
  },
  {
    "value": "1,103.52"
  },
  {
    "value": "1,718.69"
  },
  {
    "value": "1,992.83"
  },
  {
    "value": "3,796.26"
  },
  {
    "value": "3,800.43"
  },
  {
    "value": "2,128.62"
  },
  {
    "value": "2,661.56"
  }
]

Мне нужно получить среднюю сумму для каждых 5 элементов и вернуться в виде нового массива

Я нарисовал картуФункция будет работать лучше, но она не работает для меня.

 function sumAvg(arr) {
            var sum = 0;
            avg= arr.map(function(item){
              for(var i = 0; i <arr.length -1; i++){
                sum = (item.value[i] + item.value[i+1] + item.value[i+2] + item.value[i+3] + item.value[i+4])/5;
              }
              return item = sum;
            })
            return avg;
           }

           var avgString= sumAvg(jString);

           console.log(avgString);

Ответы [ 5 ]

2 голосов
/ 08 октября 2019

Ваш вопрос немного неясен, хотите ли вы, чтобы сумма каждой из последовательных 5 элементов или средняя. Вот код для получения сумм с некоторыми дополнительными примечаниями о том, как получить средние значения из этого.

const data = [{"value":"2,335.47"},{"value":"2,862.96"},{"value":"2,217.31"},{"value":"1,627.01"},{"value":"1,103.52"},{"value":"1,718.69"},{"value":"1,992.83"},{"value":"3,796.26"},{"value":"3,800.43"},{"value":"2,128.62"},{"value":"2,661.56"}];

// Create a new array
const out = [];

// While there are elements remaining
while (data.length > 0) {

  // `splice` off 5 elements from the array
  const next = data.splice(0, 5)

  // `reduce` over those 5 elements adding up the values
  // Note 1: If you want to get the average just add `/ 5`
  // to the end of this expression
  // Note 2: we have to remove the comma from the value string in
  // order to parse it properly
  const sum = next.reduce((a, b) => {
    return a + Number.parseFloat(b.value.replace(/,/g, ''));
  }, 0);

  // Push the stringified sum to the output array.
  out.push(sum.toFixed(2));
}

console.log(out);
Дополнительная литература
0 голосов
/ 08 октября 2019

Если вы хотите, чтобы в среднем каждые 5 элементов означали в среднем

0,1,2,3,4
1,2,3,4,5
2,3,4, 5,6
3,4,5,6,7

и т. Д.

Я предполагаю это, потому что похоже, что ваш код пытается это сделать

Это должно обеспечить необходимый вам результат

const input = [
      {
        "value": "2,335.47"
      },
      {
        "value": "2,862.96"
      },
      {
        "value": "2,217.31"
      },
      {
        "value": "1,627.01"
      },
      {
        "value": "1,103.52"
      },
      {
        "value": "1,718.69"
      },
      {
        "value": "1,992.83"
      },
      {
        "value": "3,796.26"
      },
      {
        "value": "3,800.43"
      },
      {
        "value": "2,128.62"
      },
      {
        "value": "2,661.56"
      }
    ];
    const result = Array.from({length:input.length-4}, (_, i) => Number((input.slice(i, i+5).reduce((acc, {value}) => acc + +value.replace(',', ''), 0)/5).toFixed(3)));
    
    console.log(result);

Относительно .toFixed(3)

Это ограничение ограничено 3 десятичными знаками, поскольку в среднем от 5 значений до 2 десятичных знаков будет только 3десятичные разряды - использование toFixed предотвращает такие значения, как 2029.2540000000001 и 2047.6619999999998, которые могут переместиться в с плавающей запятой Math

Альтернативный метод, который легче читать и, возможно, немного быстрее (например, кого это волнует, если у вас нет МИЛЛИОНОВзаписи)

const input = [
  {
    "value": "2,335.47"
  },
  {
    "value": "2,862.96"
  },
  {
    "value": "2,217.31"
  },
  {
    "value": "1,627.01"
  },
  {
    "value": "1,103.52"
  },
  {
    "value": "1,718.69"
  },
  {
    "value": "1,992.83"
  },
  {
    "value": "3,796.26"
  },
  {
    "value": "3,800.43"
  },
  {
    "value": "2,128.62"
  },
  {
    "value": "2,661.56"
  }
];

const result = 
input.slice() // copy the input
.map(({value}) => +value.replace(',', '')) // map the value's to a Number
.reduce((acc, value, i) => {
    acc.total += value; // add to the total
    let len = acc.five.push(value); // push the current value
    if (len > 5) {
        acc.total -= acc.five.shift(); // if the length has exceeded 5, reduce the total by the first value, and remove it
    }
    if (acc.five.length == 5) { // if the length is 5, output an average
        acc.result.push(Number((acc.total / 5).toFixed(3)));
    }
    return acc;
}, {five:[], result:[], total:0})
.result; // we only want the resulting array
console.log(result);
0 голосов
/ 08 октября 2019

Я бы использовал традиционные циклы и счет.

 let jString = [
    {
        "value": "2,335.47"
    },
    {
        "value": "2,862.96"
    },
    {
        "value": "2,217.31"
    },
    {
        "value": "1,627.01"
    },
    {
        "value": "1,103.52"
    },
    {
        "value": "1,718.69"
    },
    {
        "value": "1,992.83"
    },
    {
        "value": "3,796.26"
    },
    {
        "value": "3,800.43"
    },
    {
        "value": "2,128.62"
    },
    {
        "value": "2,661.56"
    }
];

let result = [];
let ctr =0;
let resIndex=0;
for(index=0; index <jString.length; index++){
    if (ctr==5) {
      ctr=0;
      result[resIndex] = result[resIndex] / 5; // avg
      resIndex++;
    }
    var value = Number(jString[index].value.replace(/,/,''));
    if (ctr == 0) {
        result.push(value);
    } else {
        result[resIndex] = result[resIndex] + value;
    }
    ctr++;
    
    // handle last records avg if they aren't 5 in total
    if (index == jString.length-1 && ctr !=5) {
        result[resIndex] = result[resIndex] / ctr; 
    }
}

console.log(result);
0 голосов
/ 08 октября 2019
function sumAvg(arr) {
            var sum = 0;
            avg= arr.map(function(item){
              for(var i = 0; i <arr.length -1; i++){
                sum = (item.value[i] + item.value[i+1] + item.value[i+2] + item.value[i+3] + item.value[i+4])/5;
              }
              return item = sum;
            })
            return avg;
           }

           var avgString= sumAvg(jString);

           console.log(avgString);

измените сумму в вашем цикле for на что-то вроде этого:

for(var i = 0; i <arr.length -1; i++){
                    sum += item.value[i];
                  }

тогда внутри цикла for вы можете получить что-то следующее:

if i == 5 then
sum = sum/5;
end if

, которое вернетсясреднее из суммы ваших 5 пунктов в вашем JSON. Я предполагаю, что это то, что вы ищете, я бы не рекомендовал это sum = (item.value [i] + item.value [i + 1] + item.value [i + 2] + item.value[i + 3] + item.value [i + 4]) / 5; Поскольку вы столкнетесь с ошибкой индексации, особенно если длина json неизвестна.

, если вы ищетепри получении среднего значения после того, как 5 значений были добавлены вместе, затем откорректируйте оператор if следующим образом:

if i % 5 == 0 then
sum = sum/5;
end if

Надеюсь, это поможет любым способом.

0 голосов
/ 08 октября 2019

Карта не будет работать так, как вы хотите. Вы выполняете вычисление для каждой группы из 5 элементов, получая некоторые из них 4 раза.

Вы можете получить первые пять элементов, сделать среднее, сохранить их где-нибудь и затем удалить их. Повторяйте это, пока массив не станет пустым

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...