根据项目的某些 属性 将数组分解为数组数组

Break an array to array of arrays based on the some of item's property

我正在使用 lodash,我想根据 属性 宽度的总和对一组对象进行分组。

我有这个数据集

[
    {id: 0, width: 2},
    {id: 1, width: 2},
    {id: 2, width: 4},
    {id: 3, width: 1},
    {id: 4, width: 3}
]

其实这是建行建列,一行的最大宽度是4

预期输出为:

[
    [{id: 0, width: 2}, {id: 1, width: 2}],
    [{id: 2, width: 4}],
    [{id: 3, width: 1}, {id: 4, width: 3}]
]

我该怎么做?

当时的想法是:

const maxWidth = 4
let currentRowWidth = 0

let newData = _.map(source, data => {
  let array = []
  if (currentRowWidth === 0) {
    currentRowWidth += data.width
    ...
    ...
  }
})

边缘情况:

  1. 如果例如当前行宽为 3,而下一列的宽度为 2。. .然后它应该移动到下一行,因为如果我们添加 3 和 2...它将超过 4.

例如

[
    [{id: 0, width: 1}, {id: 1, width: 2}],
    [{id: 2, width: 2} ...],
]

看起来像 CSS row/column 系统。 :) 这是我脑海中的一次尝试。尚未经过测试,不过应该非常接近。

function makeRows(flatArray) {
  var output = [[]];
  var currentRowWidth = 0;
  for (var i = 0; i < flatArray.length; i++) {
    if (currentRowWidth + flatArray[i].width < 4) {
      // it fits.
      currentRowWidth += flatArray[i].width;
      output[output.length - 1].push(flatArray[i];
    }
    else if (flatArray[i].width <= 4) {
      // needs a new row
      output.push([]);
      output[output.length-1].push(flatArray[i];
      currentRowWidth = flatArray[i].width
    }
    else {
      // handle your error for a row that's too wide to fit.
    }

  }
  return output;
}

如果你想在功能上做到这一点,map() 将不会真正起作用,因为它一次只知道一个元素。您需要 reduce,它会跟踪其输出并逐个构建它。

source.reduce((memo, item) => {
  if (memo.currentRowWidth + item.width <= 4) {
    memo.currentRowWidth += item.width;
    memo.output[memo.output.length -1].push(item);
  }
  else if (item.width < 4) {
    memo.push([]);
    memo.output[memo.output.length -1].push(item);
    memo.currentRowWidth += item.width;
  }
  else {
    // item.width too big, do what you want
  }
}, { currentRowWidth: 0, output: [[]] })

再说一次,未经测试,超出了我的脑海,但类似的东西。

一个使用数组进行计数的提案,它使用所有空格,而不仅仅是最后一个插槽。

var data = [{ id: 0, width: 2 }, { id: 1, width: 2 }, { id: 2, width: 4 }, { id: 3, width: 1 }, { id: 4, width: 3 }],
    max = 4,
    grouped = [];

data.forEach((count => a => {
    var index = count.findIndex(b => b + a.width <= max);
    if (index === -1) {
        index = grouped.push([]) - 1;
        count[index] = 0;
    }
    grouped[index].push(a);
    count[index] += a.width;
})([]));
console.log(grouped);

function split(arr, max) {
  max = max || 4;
  var sum = 0;
  return arr.reduce(function(rows, item) {
    // If the next column can't fit in the current row, create a new row.
    if (item.width + sum > max) {
      sum = 0;
      rows.push([]);
    }
    sum += item.width;
    rows[rows.length - 1].push(item);
    return rows;
  }, [[]]);
}

我认为这可能是答案:

var data = [{ id: 0, width: 2 }, { id: 1, width: 2 }, { id: 1, width: 2 }, { id: 2, width: 4 }, { id: 3, width: 1 }, { id: 4, width: 3 }],
    max = 4,
    group = [],
    grouped = [group,],
    width = 0;

data.forEach(d => {
  if (width + d.width > max) {
    width = 0;
    grouped.push(group = []);
  }
  width += d.width;
  group.push(d);
});

console.log(grouped)