Подсчет среднего значения ячеек столбца


#1

Добрый день!
Я написал скрипт, который генерирует матрицу MxN заполненную случайными 3-х значными числами и выводит их в таблицу.
Подсчет суммы значений ячеек в строке я уже сделал, теперь проблема возникла как посчитать среднее значение ячеек в каждом столбце и вывести их внизу в новой строке.

Вот тут можете увидеть код:

Буду благодарен за помощь :)
я там уже начал кое что писать в методе calculateColumnMid


Отрисовка сетки на canvas и событие по клику
#2

Добрый.

Лучший способ решать подобные задачи - разделить работу на части: отдельно обрабатывать данные, отдельно заниматься отрисовкой данных. В твоей реализации данные берутся из DOM элементов (calculateRowSum). Этот подход быстро сделаем невозможным добавление новых возможностей.

Предлагаю выделить в задаче специальный объект, отражающий таблицу. Все операции - добавление новых ячеек, суммирование значений, добавление новых рядов будем реализовывать через изменение этого специального объекта. И напишем одну функцию, которая будет превращать объект в DOM узлы.

Вот реализация https://codepen.io/anon/pen/YZYydW

Дополнения по коду:

  1. В объекте, отражающем ячейку, можно хранить дополнительную информацию о ячейке. Например название css класса
  2. То, что ты назвал TableConstructor на самом деле конструктором не является. Такое именование неожиданно.
  3. В решении я стремился минимально отойти от формы твоего решения. Поэтому полагаться на мое решение как на эталонное не стоит. Главная цель в моем коде - показать механизм решение задачи.
  4. Если ты пишешь код для проекта, то рекомендую найти готовое решение для работы с таблицами. Их тучи, они гибки и качественны.

#3

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

Но почему-то теперь не строится таблица когда количество колонок не равно количеству строк, например TableConstructor.init(3, 5);

почему так?


#4

Хороший вопрос. Дело в ошибке в моем коде. Как ее найти.

Мы знам что.
Каждую мутацию матрицы (добавление колонки сумм рядов, добавление ряда суммы колонок) мы реализовали как отдельный шаг. Если таблица выглядит не так как мы ожидаем, значит ошибка в одном из шагов трансформации матрицы.

Из вышесказанного следует что.
Чтобы найти шаг, который изменяет матрицу неожидаемым способом, проверим отсовку после каждого изменения.

После шага генерации

TableConstructor.init(3, 5)
//TableConstructor.matrix = TableConstructor.calculateRowSum()
//TableConstructor.matrix = TableConstructor.calculateColumnMid()
document.body.appendChild(TableConstructor.drawTable(TableConstructor.matrix))

Матрица выглядит ожидаемо.

После шага вычисления суммы рядов

TableConstructor.init(3, 5)
TableConstructor.matrix = TableConstructor.calculateRowSum()
//TableConstructor.matrix = TableConstructor.calculateColumnMid()
document.body.appendChild(TableConstructor.drawTable(TableConstructor.matrix))

И тут видим, что матрица не выглядит ожидаемым образом (количество колонок уменьшилось). Значит дело в TableConstructor.calculateRowSum(). Дальше - дело техники разобраться как должна работать функция .calculateRowSum(). На этом этапе помогают точные названия переменных.

Смотрим код:

calculateRowSum(){
	let res = []
	for (let i = 0; i < this.matrix.length; i++) {
		let row = this.matrix // это явно не ряд. Надо было бы обратиться по индексу в this.matrix[i]
		let resRow = []
		let rowSum = 0
		for (let j = 0; j < row.length; j++) {
			resRow.push(row[i][j]) // ряд не имеет такой вложенности. Или переменная названа неверно, или закралась ошибка
			rowSum += row[i][j].amount
		}
		resRow.push({
			id: this.increment++,
			amount: rowSum
		})
		res.push(resRow)
	}
	return res    	
}

Понимаем что строка вида let row = this.matrix бредятина, исправляем ее и связанные строки. Повторяем цикл проверки как отрисовываеся матрица.

Исправленный вариант:


#5

Спасибо большое, теперь работает правильно :)
Буду работать дальше)


#6

А если надо реализовать функционал увеличения значения ячейки при клике на 1, и чтобы сумма и среднее пересчитывалось соответственно, такая реализация не подойдет, надо заново всю архитектуру строить?


#7

Да. Поведение сложнее, поэтому нужна реализация похитрее. Объект, представляющий ячейки, должен мочь выражать значение ячейки через значения других ячеек. Реализация может быть разной. Надо делать выбор: вызывать метод пересчета значений самому или сделать так чтобы пересчет вызывался сам при изменении значения. Лучше, чтобы пересчет вызывался автоматически при изменнии значения ячейки.

Опиши какой функционал ты хочешь получить.


#8

Да, а вот интересно как сделать что-бы при клике добавлялась единица и и соответственно изменялась сумма и среднее?


#9

В идеале вынести данные в модель, использовать удобный фреймверк/библиотеку для отображения данных, и пересчитывать модель. В окружениях типа react+redux эта задача тривиальна.

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