根据item'的属性将数组拆分为数组的数组

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

本文关键字:数组 item 拆分 属性 根据      更新时间:2023-09-26

我使用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…

[
    [{id: 0, width: 1}, {id: 1, width: 2}],
    [{id: 2, width: 2} ...],
]
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;
  }, [[]]);
}

看起来像一个CSS行/列系统。:)这是我想到的一个尝试。还没有经过测试,但应该非常接近。

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: 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)

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

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);