Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 02.08.2021, 16:51
Аспирант
Отправить личное сообщение для dc65k Посмотреть профиль Найти все сообщения от dc65k
 
Регистрация: 19.05.2020
Сообщений: 31

Как оптимизировать функцию подсчёта данных?
Всем привет. У меня есть задача написать следующую функцию:
Данные, которые приходят на вход:
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));


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

Последний раз редактировалось dc65k, 02.08.2021 в 18:06.
Ответить с цитированием
  #2 (permalink)  
Старый 02.08.2021, 17:12
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 1,263

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

Если работает, и код вам понятен, то что и сколько вы хотите выиграть от оптимизации?
Ответить с цитированием
  #3 (permalink)  
Старый 02.08.2021, 17:18
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 1,263

Сообщение от dc65k
В целом, в условии никаких подвохов нет
Точно нет? А .flat() зачем?
Ответить с цитированием
  #4 (permalink)  
Старый 02.08.2021, 17:55
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 1,263

Ну а по мелочам...
Ну введите
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 сек, то наверно имеет смысл оптимизировать.
Ответить с цитированием
  #5 (permalink)  
Старый 02.08.2021, 18:02
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 30,970

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>

Последний раз редактировалось рони, 02.08.2021 в 18:18. Причина: заменил flat на Array.isArray()
Ответить с цитированием
  #6 (permalink)  
Старый 02.08.2021, 18:13
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 1,263

рони
Порядок элементов в массиве другой.
Сначала должны быть элементы с датами, потом total.
А итоговые products, fade, water в одном объекте
Так вроде в ТЗ
Ответить с цитированием
  #7 (permalink)  
Старый 02.08.2021, 18:21
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 30,970

voraa,
ок, не доглядел.
Ответить с цитированием
  #8 (permalink)  
Старый 02.08.2021, 18:37
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 30,970

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>
Ответить с цитированием
  #9 (permalink)  
Старый 03.08.2021, 10:31
Аватар для Vlasenko Fedor
Профессор
Отправить личное сообщение для Vlasenko Fedor Посмотреть профиль Найти все сообщения от Vlasenko Fedor
 
Регистрация: 13.03.2013
Сообщений: 1,509

dc65k, За такую структуру на выходе надо по рукам бить сразу
написание правильных форматов и структур данных - один из факторов, который должен обладать программист. Структуры и данные, должны быть понятны и читабельны.
Вы же загнали разные типы данных в массив, с которым и работать после будет не совсем удобно
Ответить с цитированием
  #10 (permalink)  
Старый 03.08.2021, 11:40
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 13,310

Сообщение от Vlasenko Fedor
За такую структуру на выходе надо по рукам бить сразу
Может это просто упражнение, которое придумали "на скорую руку".
Согласен что фигня полная... Но просто как упражнение с некой долей сложности.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как сделать короткую функцию для forEach? nastya97core Общие вопросы Javascript 11 14.05.2020 07:12
Получить имя функции внутри функции не используя callee drwhite Общие вопросы Javascript 39 12.02.2020 21:48
как передать измененные параметры AJAX в другую функцию? akselei Элементы интерфейса 2 19.10.2013 11:46
Управление скроллом "а-ля тач" HonesT Элементы интерфейса 2 27.08.2013 13:25
как реализовать передачу функции в функцию?? czp Общие вопросы Javascript 10 29.11.2011 17:21