如何在js中对数组中的数据进行分组

Posted

技术标签:

【中文标题】如何在js中对数组中的数据进行分组【英文标题】:How to grouping data from array in js 【发布时间】:2022-01-13 02:51:56 【问题描述】:

我有一个包含不同对象的数组,其中每个对象都是一个类。看起来像这样:

sessions = [
       session_id: 1, time: '09:00', student:  student_id: 1, name: 'Adi' , class:  class_id: 1, name: 'A'  ,
       session_id: 2, time: '10:00', student:  student_id: 7, name: 'Dede' , class:  class_id: 4, name: 'D'  ,
       session_id: 1, time: '09:00', student:  student_id: 3, name: 'Bayu' , class:  class_id: 2, name: 'B'  ,
       session_id: 1, time: '09:00', student:  student_id: 2, name: 'Budi' , class:  class_id: 1, name: 'A'  ,
       session_id: 2, time: '10:00', student:  student_id: 3, name: 'Maha' , class:  class_id: 3, name: 'C'  ,
    ];

我想把数据改成这样,(按session_id或时间分组):

sessions = [
   
     session_id: 1,
     time: '09:00',
     classes: [
       
         class_id: 1,
         name: 'A',
         students: [
            student_id: 1, name: 'Adi' ,
            student_id: 1, name: 'Budi' ,
         ],
       ,
       
         class_id: 2,
         name: 'B',
         students: [
            student_id: 3, name: 'Bayu' ,
         ],
       ,
     ],
   ,
   
     session_id: 2,
     time: '10:00',
     classes: [
       
         class_id: 3,
         name: 'C',
         students: [
            student_id: 6, name: 'Maha' ,
         ],
       ,
       
         class_id: 4,
         name: 'D',
         students: [
            student_id: 7, name: 'Dede' ,
         ],
       ,
     ],
   ,
  ];

    

我厌倦了尝试解决它,因为我的 javascript 不是那么好。请帮我解决代码。

【问题讨论】:

【参考方案1】:

我们可以使用Array.reduce(),按 session_id 分组,然后在每个会话中添加班级和学生(如果不存在):

const sessions = [
   session_id: 1, time: '09:00', student:  student_id: 1, name: 'Adi' , class:  class_id: 1, name: 'A'  ,
   session_id: 2, time: '10:00', student:  student_id: 7, name: 'Dede' , class:  class_id: 4, name: 'D'  ,
   session_id: 1, time: '09:00', student:  student_id: 3, name: 'Bayu' , class:  class_id: 2, name: 'B'  ,
   session_id: 1, time: '09:00', student:  student_id: 2, name: 'Budi' , class:  class_id: 1, name: 'A'  ,
   session_id: 2, time: '10:00', student:  student_id: 3, name: 'Maha' , class:  class_id: 3, name: 'C'  ,
];

const result = Object.values(sessions.reduce((acc,  session_id, time, student, ['class']:  class_id, name ) => 
    acc[session_id] = acc[session_id] ||  session_id, time, classes: [] ;
    let cl = acc[session_id].classes.find(c => c.class_id === class_id);
    if (!cl) 
        cl =  class_id, name, students: []
        acc[session_id].classes.push(cl); 
     
    cl.students.push(student);
    return acc;
, ));

console.log('Result:', result);
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

【参考方案2】:

您可以使用lodash.groupBy。例如:

const sessions = [
     session_id: 1, time: '09:00', student:  student_id: 1, name: 'Adi' , class:  class_id: 1, name: 'A'  ,
     session_id: 2, time: '10:00', student:  student_id: 7, name: 'Dede' , class:  class_id: 4, name: 'D'  ,
     session_id: 1, time: '09:00', student:  student_id: 3, name: 'Bayu' , class:  class_id: 2, name: 'B'  ,
     session_id: 1, time: '09:00', student:  student_id: 2, name: 'Budi' , class:  class_id: 1, name: 'A'  ,
     session_id: 2, time: '10:00', student:  student_id: 3, name: 'Maha' , class:  class_id: 3, name: 'C'  ,
];
const result = Object.entries(_.groupBy(sessions, 'session_id')).map(session => ( session_id: Number(session[0]), time: session[1][0].time, classes: Object.entries(_.groupBy(session[1], s => s.class.class_id)).map(c => ( class_id: Number(c[0]), name: c[1][0].class.name, students: c[1].map(x => ( student_id: x.student.student_id, name: x.student.name )) )) ))
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

【讨论】:

可读性不是很强,不过可以封装一些函数【参考方案3】:

试试下面的sn-p:

const sessions = [
       session_id: 1, time: '09:00', student:  student_id: 1, name: 'Adi' , class:  class_id: 1, name: 'A'  ,
       session_id: 2, time: '10:00', student:  student_id: 7, name: 'Dede' , class:  class_id: 4, name: 'D'  ,
       session_id: 1, time: '09:00', student:  student_id: 3, name: 'Bayu' , class:  class_id: 2, name: 'B'  ,
       session_id: 1, time: '09:00', student:  student_id: 2, name: 'Budi' , class:  class_id: 1, name: 'A'  ,
       session_id: 2, time: '10:00', student:  student_id: 3, name: 'Maha' , class:  class_id: 3, name: 'C'  ,
    ];

const newSessions = sessions.reduce((acc, session)=> 
    const sessionIndex = acc.findIndex(item => item.session_id == session.session_id);
    if(sessionIndex > -1)
        updateSessionClasses(acc[sessionIndex], session)
    else 
        acc.push( session_id: session.session_id, time: session.time, classes: [...session.class, students: [session.student]]  )
    ;
    return acc;
, []);

function updateSessionClasses(storedSession, session)
    const classIndex = storedSession.classes.findIndex(c => c.class_id == session.class.class_id);
    if(classIndex > -1)
      storedSession.classes[classIndex].students.push(session.student)
    else 
       storedSession.classes.push(...session.class, students: [session.student]) 
    


console.log(newSessions)

【讨论】:

【参考方案4】:

sessions = [
   session_id: 1, time: '09:00', student:  student_id: 1, name: 'Adi' , class:  class_id: 1, name: 'A'  ,
   session_id: 2, time: '10:00', student:  student_id: 7, name: 'Dede' , class:  class_id: 4, name: 'D'  ,
   session_id: 1, time: '09:00', student:  student_id: 3, name: 'Bayu' , class:  class_id: 2, name: 'B'  ,
   session_id: 1, time: '09:00', student:  student_id: 2, name: 'Budi' , class:  class_id: 1, name: 'A'  ,
   session_id: 2, time: '10:00', student:  student_id: 3, name: 'Maha' , class:  class_id: 3, name: 'C'  ,
];

const studentsRedused = sessions.reduce((acc,  session_id, student, class:  class_id  ) => 
  const session_class = `$session_id-$class_id`;
  acc[session_class] = acc[session_class]
    ? [...acc[session_class],  ...student ]
    : [ ...student ]
  return acc;
, );

const classesRedused = sessions.reduce((acc,  session_id, class:  class_id, name  ) => 
  const needAddClass = acc[session_id] ? !acc[session_id].some((o) => o.class_id === class_id) : true
  if (needAddClass) 
    acc[session_id] = acc[session_id]
      ? [...acc[session_id],  class_id, name ]
      : [ class_id, name ]
  
  return acc;
, );

const reduced = sessions.reduce((acc,  session_id, time, class:  class_id, name  ) => 
  const classes = classesRedused[session_id].map((objClass) => 
    const session_class = `$session_id-$objClass.class_id`;
    return   ...objClass, students: studentsRedused[session_class] 
  );
  acc[session_id] =  session_id, time, classes 
  return acc;
, );

const result = Object.values(reduced);

console.dir(result, depth: null);
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

以上是关于如何在js中对数组中的数据进行分组的主要内容,如果未能解决你的问题,请参考以下文章

你将如何在 python 的数组中对这三个区域进行分组/聚类?

如何在 React Native 中对数组进行分组

如何在 Hive SQL 中对一列中的数据进行分组并将其分布在另一列中?

如何在 ASP.NET MVC 视图中对数据进行分组?

如何在每个循环中对 Json 对象进行分组

如何在SQL中对相邻行进行分组并对数据求和