以这个极其简化的对象数组为例:
[
{
createID: '1'
// Many other properties...
},
{
createID: '1'
// Many other properties...
},
{
createID: '1'
// Many other properties...
},
{
createID: '37'
// Many other properties...
},
{
createID: '37'
// Many other properties...
},
{
createID: '2'
// Many other properties...
},
{
createID: '2'
// Many other properties...
},
{
createID: '14'
// Many other properties...
},
];
鉴于此数组,我然后使用对象createID
属性创建一个包含对象[[{..},{..}], [{..}], ..n]
的数组数组。我正在使用的当前前端框架(Angular v6)要求使用这种最终格式。
要完成此任务,我使用以下代码,其中tempArr
是一个类似于上面提供的示例数组的数组。
let currentGroup: string = tempArr[0].createID;
let tempGrouped: any[] = [];
let childGroup: any[] = [];
tempArr.forEach(item => {
if (item.createID !== currentGroup) {
tempGrouped.push(childGroup);
childGroup = [];
currentGroup = item.createID;
}
childGroup.push(item);
});
tempGrouped.push(childGroup);
此代码可以正常工作。但是,我不禁相信在给定数据的基础上,必须有一种更有效,更优雅的方法将对象数组转换为包含对象的数组。
createID
的只是ID表示应该将哪些对象分组在一起。因此,不需要createID
对它们进行数字排序。另外,对象确实来自与它们的同级对象(与createID
相同)的服务器“分组”,如在提供的给定示例数组中所见。
答案 0 :(得分:1)
您的示例具有彼此相邻的所有相同ID。如果可以保证总是这样,则只需要遍历并推送到新数组即可。但是,如果不是这种情况,您的解决方案将无法正确分组项目。在这种情况下,使用哈希表将使您仍可以按渐近复杂度按ID分组。
您可以使用从createdID
创建的键将对象分组为哈希表对象。这将使您有效地对所有内容进行分组。然后只需从哈希表中获取对象:
let arr = [{createID: '1'},{createID: '1'},{createID: '1'},{createID: '37'},{createID: '37'},{createID: '2'},{createID: '2'},{createID: '14'},];
let o = arr.reduce((a, c) => {
(a[c.createID] || (a[c.createID] = [])).push(c)
return a
}, {} )
// o is a an object with createID keys pointing to arrays of grouped objects
// just take the values
console.log(Object.values(o))
根据问题进行编辑
由于对象已经被分组,没有比循环遍历更好的方法了。如果您想要一个不添加临时数组的选项,则仍然可以使用reduce()
,它与您当前的解决方案基本相同,但是可能更独立一些:
let tempArr = [{createID: '1'},{createID: '1'},{createID: '1'},{createID: '37'},{createID: '37'},{createID: '2'},{createID: '2'},{createID: '14'},];
let r = tempArr.reduce((a, c, i, self) => {
if (i === 0 || self[i-1].createID !== c.createID)
a.push([])
a[a.length - 1].push(c)
return a
}, [])
console.log(r)
答案 1 :(得分:1)
假设您的数据数组存储在名为data
的变量中:
const result = data.reduce((acc, current) => {
if (!acc.dictionary[current.createID]) {
const createIdArray = [];
acc.dictionary[current.createID] = createIdArray;
acc.array.push(createIdArray);
}
acc.dictionary[current.createID].push(current);
return acc;
}, {array: [], dictionary: {}}).array;
这样,您将仅对数据循环一次,这非常有效,因为我们不使用过滤器或查找(这会一次又一次遍历整个数组)。
以下是输出:
[
[
{
createID: '1',
},
{
createID: '1',
},
{
createID: '1',
},
],
[
{
createID: '37',
},
{
createID: '37',
},
],
[
{
createID: '2',
},
{
createID: '2',
},
],
[
{
createID: '14',
},
],
];
这是一个正在运行的演示:https://stackblitz.com/edit/typescript-phbzug
摘要:
答案 2 :(得分:-1)
您要按createID分组吗?
let grouped=tempArray
//first get uniq values
.filter((s,index)=>tempArray.findIndex(f=>f.createID==s.createID)==index)
//then, with the uniq values make a map
.map(seg=>{ //with each uniq value, create an object with two properties
return {
createID:seg.createID, //the key
items:tempArray.filter(s=>s.createID==seg.createID) //An array with the values
}
})