[英]javascript create array of objects with a fixed length based on another bigger array
給定一個偶數長度的數組:
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]
,如果有一個這個新的分塊數組中有更多的項目,那么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的長度至少為2,這意味着路徑和two
存在於每個新對象中。
一個基本的例子是,如果原始數組是三個,那么我們就不能將其平均划分為較小的塊,因此:
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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.