根据项目的某些 属性 将数组分解为数组数组
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
...
...
}
})
边缘情况:
- 如果例如当前行宽为 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)
我正在使用 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
...
...
}
})
边缘情况:
- 如果例如当前行宽为 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)