Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Как оптимизировать функцию подсчёта данных? (https://javascript.ru/forum/dom-window/82909-kak-optimizirovat-funkciyu-podschjota-dannykh.html)

dc65k 02.08.2021 16:51

Как оптимизировать функцию подсчёта данных?
 
Всем привет. У меня есть задача написать следующую функцию:
Данные, которые приходят на вход:
const array = [
  {
    '2021-07-01': {
      'products': [1661.28, 229],
    },
  },
  {
    '2021-07-02': {
      'fare': [66, 78],
      'products': 218,
    }
  },
  {
    '2021-07-03': {
      'fare': 78,
      'products': 909.80,
    }
  },
  {
    '2021-07-05': {
      'water': 840,
      'products': 1021.61,
    },
  },
]


Данные, которые необходимо получить:
[
  { '2021-07-01': '1890.28' },
  { '2021-07-02': '362.00' },
  { '2021-07-03': '987.80' },
  { '2021-07-05': '1861.61' },
  { total: '5101.69' },
  { fare: '222.00', products: '4039.69', water: '840.00' }
]


Функция считает сумму за день, общую сумму, и общую сумму за каждую позицию. В целом, в условии никаких подвохов нет

Моё решение:
const array = [
  {
    '2021-07-01': {
      'products': [1661.28, 229],
    },
  },
  {
    '2021-07-02': {
      'fare': [66, 78],
      'products': 218,
    }
  },
  {
    '2021-07-03': {
      'fare': 78,
      'products': 909.80,
    }
  },
  {
    '2021-07-05': {
      'water': 840,
      'products': 1021.61,
    },
  },
]

const calculate = array => {

  const digits = 2;

  let total = 0;

  let object = {};

  const output = array.reduce((accumulator, currentValue, index, array) => {

    const prop = {};

    const date = Object.keys(currentValue)[0];

    for (const value of Object.keys(currentValue[date])) {
      if (!object[value]) {
        object[value] = 0;
      }

      object[value] += sum(currentValue[date][value]);
    }

    prop[date] = sum(Object.values(currentValue[date]).flat()).toFixed(digits);

    total += sum(Object.values(currentValue[date]).flat());

    accumulator.push(prop);

    if (index === array.length - 1) {
      accumulator.push({
        total: total.toFixed(digits)
      });
    }

    return accumulator;
  }, []);

  output.push(Object.keys(object).sort().reduce((accumulator, currentValue) => {
    accumulator[currentValue] = object[currentValue].toFixed(digits);
    return accumulator;
  }, {}));

  return output;
};

const sum = input => {
  if (Array.isArray(input)) {
    return input.reduce((accumulator, currentValue) => accumulator += currentValue, 0);
  }

  return input;
};

console.log(calculate(array));


Подскажите, как решение можно оптимизировать?

voraa 02.08.2021 17:12

А по каким критериям оптимизировать?
По количеству символов?
По времени исполнения?
По объему требуемой памяти?

Если работает, и код вам понятен, то что и сколько вы хотите выиграть от оптимизации?

voraa 02.08.2021 17:18

Цитата:

Сообщение от dc65k
В целом, в условии никаких подвохов нет

Точно нет? А .flat() зачем?

voraa 02.08.2021 17:55

Ну а по мелочам...
Ну введите
let currentDate = currentValue[date];

И замените везде currentValue[date]. Уж больно часто встречается

Строки 42-46 замените на

object[value] = (object[value] || 0) + sum(currentDate[value]);


Уберите строки 55-59, а после строки 62

output.push( {total: total.toFixed(digits)} );


Учтите, что всякие reduce, forEach, map по скорости существенно проигрывают обычному for( ; ; ). Но при разнице в 2-3 мс это не играет ни какой роли. А если в массиве сотни тысяч элементов и разница будет в 2-3 сек, то наверно имеет смысл оптимизировать.

рони 02.08.2021 18:02

dc65k,
<pre>

    <script>
const array = [{
        '2021-07-01': {
            'products': [1661.28, 229],
        },
    },
    {
        '2021-07-02': {
            'fare': [66, 78],
            'products': 218,
        }
    },
    {
        '2021-07-03': {
            'fare': 78,
            'products': 909.80,
        }
    },
    {
        '2021-07-05': {
            'water': 840,
            'products': 1021.61,
        },
    },
]
const calculate = array => Object.entries(array.reduce((obj, a) => {
    let [key, value] = Object.entries(a)[0], sum = 0;
    for (let k in value) {
        k in obj || (obj[k] = 0);
        let temp = value[k];
        if(Array.isArray(temp)) temp = temp.reduce((a, b) => a + b, 0);
        obj[k] += temp;
        sum += temp
    }
    obj[key] = sum;
    obj.total += sum;
    return obj
}, { total: 0 })).map(([a, b]) => ({[a]: b.toFixed(2)}))
document.write(JSON.stringify(calculate(array), "", 1));
</script></pre>

voraa 02.08.2021 18:13

рони
Порядок элементов в массиве другой.
Сначала должны быть элементы с датами, потом total.
А итоговые products, fade, water в одном объекте
Так вроде в ТЗ

рони 02.08.2021 18:21

voraa,
ок, не доглядел.

рони 02.08.2021 18:37

dc65k,
<pre>

    <script>
const array = [{
        '2021-07-01': {
            'products': [1661.28, 229],
        },
    },
    {
        '2021-07-02': {
            'fare': [66, 78],
            'products': 218,
        }
    },
    {
        '2021-07-03': {
            'fare': 78,
            'products': 909.80,
        }
    },
    {
        '2021-07-05': {
            'water': 840,
            'products': 1021.61,
        },
    },
]
const calculate = array => {
    let obj = {}, total = 0
    array = array.map(a => {
        let [key, value] = Object.entries(a)[0], sum = 0;
        for (let k in value) {
            k in obj || (obj[k] = 0);
            let temp = value[k];
            if (Array.isArray(temp)) temp = temp.reduce((a, b) => a + b, 0);
            obj[k] += temp;
            sum += temp
        }
        total += sum
        return {
            [key]: sum.toFixed(2)
        }

    });
    total = total.toFixed(2);
    array.push({ total });
    for (let k in obj) obj[k] = obj[k].toFixed(2);
    array.push(obj);
    return array

}

document.write(JSON.stringify(calculate(array), "", 1));
</script></pre>

Vlasenko Fedor 03.08.2021 10:31

dc65k, За такую структуру на выходе надо по рукам бить сразу
написание правильных форматов и структур данных - один из факторов, который должен обладать программист. Структуры и данные, должны быть понятны и читабельны.
Вы же загнали разные типы данных в массив, с которым и работать после будет не совсем удобно :cray:

ksa 03.08.2021 11:40

Цитата:

Сообщение от Vlasenko Fedor
За такую структуру на выходе надо по рукам бить сразу

Может это просто упражнение, которое придумали "на скорую руку". :)
Согласен что фигня полная... Но просто как упражнение с некой долей сложности.


Часовой пояс GMT +3, время: 17:46.