【发布时间】:2021-03-03 06:26:42
【问题描述】:
我需要删除我创建的函数中的嵌套 for 循环。 我的函数接收一个关联数组,然后我根据某些属性返回一个新数组,以便对消息进行分组以供以后使用。 比如我有两所学校,很多学生。所以我根据性别和年级对他们进行分组。 我不怎么重构这个函数,因为我对算法不太了解。 我的逻辑是需要完全删除还是需要再次完成都没关系。我必须删除第二个 for 循环。此外,我可以返回一个公共数组、关联数组或仅返回一个对象。 我试图用相同的逻辑但不同的数据复制我的函数:
var studentsArray = new Array();
studentsArray["SCHOOL_1"] = [
// girls
{id: '1', school: 'SCHOOL_1', grade: 'A', message: 'Congratulations!', isMan: false},
{id: '2', school: 'SCHOOL_1', grade: 'A', message: 'Good work!', isMan: false},
{id: '3', school: 'SCHOOL_1', grade: 'A', message: 'Ok', isMan: false},
// boys
{id: '4', school: 'SCHOOL_1', grade: 'A', message: 'Congratulations!', isMan: true},
{id: '5', school: 'SCHOOL_1', grade: 'B', message: 'Good work!', isMan: true},
{id: '6', school: 'SCHOOL_1', grade: 'B', message: 'Good work!', isMan: true},
{id: '7', school: 'SCHOOL_1', grade: 'A', message: 'Congratulations!', isMan: true},
{id: '8', school: 'SCHOOL_1', grade: 'B', message: 'Good work!', isMan: true},
];
studentsArray["SCHOOL_2"] = [
// girls
{id: '9', school: 'SCHOOL_2', grade: 'A', message: 'Congratulations!', isMan: false},
{id: '10', school: 'SCHOOL_2', grade: 'A', message: 'Congratulations!', isMan: false},
{id: '11', school: 'SCHOOL_2', grade: 'A', message: 'Congratulations!', isMan: false},
{id: '12', school: 'SCHOOL_2', grade: 'B', message: 'Good work!', isMan: false},
{id: '13', school: 'SCHOOL_2', grade: 'B', message: 'Nice!', isMan: false},
// boys
{id: '14', school: 'SCHOOL_2', grade: 'A', message: 'Congratulations!', isMan: true},
{id: '15', school: 'SCHOOL_2', grade: 'A', message: 'Congratulations!', isMan: true},
{id: '16', school: 'SCHOOL_2', grade: 'A', message: 'Congratulations!', isMan: true},
{id: '17', school: 'SCHOOL_2', grade: 'B', message: 'Congratulations!', isMan: true},
];
function GroupMessages(schools, gender) {
// Initialize object to return
var result = [];
// First loop
for (var school in schools) {
// Group students by gender
var girls = schools[school].filter(student => !student.isMan);
var boys = schools[school].filter(student => student.isMan);
// Flag to determine unique grade per gender
var boysHaveUniqueGrade = boys.map(student => student.grade).filter((v, i, a) => a.indexOf(v) === i).length === 1;
var girlsHaveUniqueGrade = girls.map(student => student.grade).filter((v, i, a) => a.indexOf(v) === i).length === 1;
// If exists a single student per gender, return the same
if (girls && girls.length === 1) result.push(girls[0]);
if (boys && boys.length === 1) result.push(boys[0]);
//////////////////////////
// Group by grades //
/////////////////////////
if (boys && boys.length > 1 && boysHaveUniqueGrade && gender === 'man') {
// Combine messages
let messages = boys.map(boy => boy.message);
// First student is the reference
let student = boys[0];
// Join messages
student.message = messages.join('|');
// Update object to return
result.push(student);
}
if (boys && boys.length > 1 && !boysHaveUniqueGrade && gender === 'man') {
// Group messages by level (maybe I don't need GroupByProperty function neither)
let studentsByGrade = GroupByProperty(boys, 'grade');
// Second loop. I return a boys students based on 'grade' property. (I NEED TO DELETE THIS SECOND FOR LOOP)
for (let grade in studentsByGrade) {
// First student is the reference
let student = studentsByGrade[grade][0];
// Combine messages
let messages = studentsByGrade[grade].map(student => student.message);
// Join messages
student.message = messages.join('|');
// Update object to return
result.push(student);
// Code continue but I stop code here...
}
}
if (girls && girls.length > 1 && girlsHaveUniqueGrade && gender !== 'man') {
// Combine messages
let messages = girls.map(girl => girl.message);
// First student is the reference
let student = girls[0];
// Join messages
student.message = messages.join('|');
// Update object to return
result.push(student);
}
if (girls && girls.length > 1 && !girlsHaveUniqueGrade && gender !== 'man') {
// Group messages by level (maybe I don't need GroupByProperty function neither)
let studentsByGrade = GroupByProperty(girls, 'grade');
// Second loop. I return a girls students based on 'grade' property. (I NEED TO DELETE THIS SECOND FOR LOOP)
for (let grade in studentsByGrade) {
// First student is the reference
let student = studentsByGrade[grade][0];
// Combine messages
let messages = studentsByGrade[grade].map(student => student.message);
// Join messages
student.message = messages.join('|');
// Update object to return
result.push(student);
// Code continue but I stop code here...
}
}
}
return result;
}
function GroupByProperty(objectArray, property) {
let result = objectArray.reduce((acc, obj) => {
var key = obj[property];
if (!acc[key]) acc[key] = [];
acc[key].push(obj);
return acc;
}, {});
return result;
}
GroupMessages(studentsArray, 'woman'); // any other gender works as 'man'
【问题讨论】:
-
预期输出是什么?
-
一个数组、关联数组或对象,可根据学生的性别和成绩对学生进行分组或过滤。您必须考虑到性别和成绩可能不同。
-
There are no "associative arrays" in JavaScript。使用对象文字,不要使用
new Array。 -
谢谢@Bergi。我刚刚在示例函数中添加了一个参数。我希望有人可以帮助我。
-
@Intenzion,能否请您包括您遗漏的部分,例如
code with another logic。查看预期的输出也会很有帮助。
标签: javascript arrays algorithm loops for-loop