ms-dred
@ms-dred
Вечно что то не то и что то не так...

Как равномерно заполнить 3 массива с учетом высоты элементов?

Мне нужно раскидать элементы по многомерному массиву с учетом их высоты, чтобы в конечном итоге общая "высота" каждого массива была близка к "высоте" остальных массивов. Но перерисовывать массивы не нужно, нужно просто последовательное раскидать объекты по массивом с учетом высоты.

Получается многомерный массив с 3 массивами и есть 100 объектов которые необходимо раскидать по этим массивам последовательно, у каждого из объектов прописана высота ({height: Number})

Есть цикл который последовательно перебирает массив объектов и пушит объекты по индексу массива у котором сумма высот объектов меньше остальных.

Вот неудачная попутка осуществить задуманное
const data = [
    { height: 10 },
    { height: 20 },
    { height: 30 },
    { height: 20 },
    { height: 40 },
    { height: 60 },
    { height: 10 },
    { height: 30 },
    { height: 70 },
    { height: 50 },
    { height: 110 },
    { height: 90 }
]
const columnHeight = Array.from({ length: 3 }, () => 0)
const columns = Array.from({ length: 3 }, () => [])


data.map((e, i) => {
    const { height } = e

    const indexMin = columnHeight.indexOf(Math.min.apply(null, columnHeight)) 
    columnHeight[indexMin] = columnHeight[indexMin] + height

    columns[indexMin].push(e)

})


При это вывод следующий
//console.log(columns)
[
    [{ height: 10 }, { height: 20 }, { height: 60 }, { height: 110 }],
    [{ height: 20 }, { height: 40 }, { height: 70 }],
    [{ height: 30 }, { height: 10 }, { height: 30 }, { height: 50 }, { height: 90 }]
]


А должен быть
[
    [{ height: 10 }, { height: 20 }, { height: 10 }, { height: 30 }, { height: 70 },], // 140
    [{ height: 20 }, { height: 60 }, { height: 110 },], // 190
    [{ height: 30 }, { height: 40 }, { height: 50 }, { height: 90 }] // 210
]
  • Вопрос задан
  • 80 просмотров
Решения вопроса 1
bingo347
@bingo347 Куратор тега JavaScript
Crazy on performance...
Ошибка в том что columnHeight нужно обновлять по тому же индексу, что и columns.
Ну еще есть проблемы с тем, что исходные данные не упорядочены, а значит массивы будут заполняться не равномерно. Притом сортировать лучше по убыванию.
Так же, если нужен оригинальный порядок, то его нужно сохранить, а потом так же восстанавливать сортировкой.

// Сохраняем исходные индексы и сортируем по высоте по убыванию
const preparedData = data
    .map((e, i) => ({i, e}))
    .sort((a, b) => b.e.height - a.e.height);

for (const el of preparedData) {
    const { height } = el.e;
    // тут никогда не вернет -1, так как мы ищем элемент который точно есть в массиве - минимальный
    const index = columnHeight.indexOf(Math.min(...columnHeight));
    // обновляем данные массивов по выбранному индексу
    columnHeight[index] += height;
    columns[index].push(el);
}

// нормализуем columns
for (let i = 0; i < columns.length; ++i) {
    // восстановим исходный порядок, отсортировав по сохраненному индексу по возрастанию
    columns[i].sort((a, b) => a.i - b.i);
    // избавимся от сохраненных индексов, оставив только исходные объекты
    columns[i] = columns[i].map(({ e }) => e);
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы