javascript根据另一个更大的数组创建具有固定长度的对象数组
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript根据另一个更大的数组创建具有固定长度的对象数组相关的知识,希望对你有一定的参考价值。
给定一个偶数长度的数组:
const items = [
'this/is/path1',
'this/is/path2',
'this/is/path3',
'this/is/path4',
'this/is/path5',
'this/is/path6'
];
我想创建一个具有一定长度objnb
的对象数组。根据这个长度,我将上面的items
分成块,然后将第一个索引存储在一个新的对象属性path
上,以及other1
中的以下元素,other2
;其他对象块也是如此。
我的解决方案是hacky:
const objnb = 2;
const other1 = true;
const other2 = true;
const outputobjs = items.length / objnb;
const result = items.map((entry, index) => {
let obj = {};
console.log({ entry, index })
if (index % outputobjs === 0) {
obj.path = entry;
obj.others = {};
if (other1) {
obj.others.two = items[index + 1];
}
if (other2) {
obj.others.three = items[index + 2];
}
return obj;
}
return obj;
})
console.log('result: ', result)
输出是正确的:
[ { path: 'this/is/path1',
others: { two: 'this/is/path2', three: 'this/is/path3' } },
{},
{},
{ path: 'this/is/path4',
others: { two: 'this/is/path5', three: 'this/is/path6' } },
{},
{} ]
但不幸的是,我得到了空的物品,我不想要。如何以更清洁的方式实现同样的目标?
首选结果不包含空对象。
更新
另一个例子是:
const items = [
'this/is/path1',
'this/is/path2',
'this/is/path3',
'this/is/path4'
];
const objnb = 2;
const other1 = true;
const other2 = false;
const outputobjs = items.length / objnb;
const result = items.map((entry, index) => {
let obj = {};
console.log({ entry, index })
if (index % outputobjs === 0) {
obj.path = entry;
obj.others = {};
if (other1) {
obj.others.two = items[index + 1];
}
if (other2) {
obj.others.three = items[index + 2];
}
return obj;
}
return obj;
})
console.log('result: ', result)
结果是:
[ { path: 'this/is/path1', others: { two: 'this/is/path2' } },
{},
{ path: 'this/is/path3', others: { two: 'this/is/path4' } },
{} ]
澄清:
新数组中的每个对象都是相似的,例如,它们都将具有path
,并且由于我们正在均匀地划分原始数组,因此新对象将具有所有相同的属性。例如,如果有一个two
,则新数组中的其余对象都将具有此属性,如果它们应该具有three
,则它们都将具有该属性。
新对象将如下所示:
{ path: 'this/is/path1',
others: {
two: 'this/is/path2',
three: 'this/is/path3' // optional; if one object has this, others must have it too.
}
}
所以基本上,通过将原始项目数组划分为特定数字,2,3或4等...我们将其分成较小的数组,新对象path
将为chunkedArray[0]
,如果还有一个项目这个新的chunked数组,然后two
将是chunkedArray[1]
,如果还剩下一个,那么three
将是chunkedArray[2]
所以,如果我们除以2,那么我们将:
const chunkedArray1 = [
'this/is/path1', // path
'this/is/path2', //others.two
'this/is/path3' //others.three
];
const chunkedArray2 = [
'this/is/path4',// path
'this/is/path5',//others.two
'this/is/path6'//others.three
];
因此新的物体将有two
和three
;
但如果我们把它分成3,我们将:
const chunkedArray1 = [
'this/is/path1',// path
'this/is/path2'//others.two
];
const chunkedArray2 = [
'this/is/path3',// path
'this/is/path4'//others.two
];
const chunkedArray3 = [
'this/is/path5',// path
'this/is/path6'//others.two
];
所以我们每个对象只有路径和two
。
每个新的chunkedArray至少有两个长度,这意味着每个新对象中都存在路径和two
。
另一个例子:
一个基本的例子是,如果原始数组为3,那么我们不能将它均匀地划分为较小的块,因此:
const items = [
'this/is/path1', //path
'this/is/path2',//others.two
'this/is/path3'//others.three
];
和此相同,如果原始数组是两个长度:
const items = [
'this/is/path1', //path
'this/is/path2',//others.two
];
下面是一个使用reduce
的解决方案。
const items = [
'this/is/path1',
'this/is/path2',
'this/is/path3',
'this/is/path4',
'this/is/path5',
'this/is/path6'
]
function splitItems(data, chunkSize) {
if (chunkSize < 2) return data // or the special value you'd like.
const labels = {
1: 'one',
2: 'two',
3: 'three',
4: 'four'
// ... others
}
return data.reduce((pre, cur, index) => {
if (index % chunkSize === 0) {
/* for old question
pre.push({
path: cur,
others: {}
})*/
let newItem = {
path: cur,
others: {}
}
Array.from(Array(chunkSize-1).keys()).map( itemIndex => {
newItem.others[labels[(itemIndex+1) % chunkSize + 1]] = '' //or other default valu
})
pre.push(newItem)
}
else {
pre[pre.length - 1].others[labels[index % chunkSize + 1]] = items[index]
}
return pre
}, [])
}
console.log('@Test Case 1@', splitItems(items, 2), '@@')
console.log('@Test Case 2@', splitItems(items.slice(0, 2), 2), '@@')
console.log('@Test Case 3@', splitItems(items.slice(0, 4), 2), '@@')
console.log('@Test Case 4@', splitItems(items.slice(0, 5), 3), '@@')
// calc the size first, then exec splitItems
function splitByLength(data, numberOfChunks) {
let chunkSize = Math.round(data.length/3, 0)
return splitItems(data, chunkSize)
}
console.log('@Test Case 5@', splitByLength(items.slice(0, 5), 3), '@@')
简而言之,您可以循环每个第3项并将其作为对象推送。
const items = [
'this/is/path1',
'this/is/path2',
'this/is/path3',
'this/is/path4',
'this/is/path5',
'this/is/path6'
];
var result = [];
for(var i = 0; i < items.length; i++){
if(i%3==0){
result.push({
path: items[i],
others: {two: items[i+1] || null, three: items[i+2] || null}
})
}
}
console.log(result)
使用reduce的另一个解决方案,与@sphinx答案略有不同,虽然非常相似:
const objnb = 3;
const otherKeys = ['two', 'three'];
const items = [
'this/is/path1',
'this/is/path2',
'this/is/path3',
'this/is/path4',
'this/is/path5',
'this/is/path6'
];
const outputobjs = Math.ceil(items.length / objnb);
const ar = items.reduce((memo, item, index) => {
const mod = index % outputobjs
if(mod === 0)
memo.push({path: item, others: {}});
else if(mod <= otherKeys.length)
Object.assign(memo[memo.length - 1].others, {[otherKeys[mod -1]]: item});
return memo;
}, []);
console.log(ar);
以上是关于javascript根据另一个更大的数组创建具有固定长度的对象数组的主要内容,如果未能解决你的问题,请参考以下文章
在 for 循环中删除和添加 numpy 数组行以从更大的 numpy 数组创建动态子数组,
JavaScript 根据使用数组从另一个下拉列表中的选择动态创建选项