使用 lodash 而不是 for 循环
use lodash instead of forloop
我是 lodash 的新手,我想将这个使用 i 和 j 的 forloop 转换为 lodash,这样我的编码就减少了。
for(var i =0 ; i < students.length; i++){
for(var j = 0; j <marks.lab.length;j++){
if(students[i].sID === marks.lab[j].sID){
students[i].coding = data.lab[j].coding;
}
}
}
如果使用 lodash 还有其他优势,请告诉我。
从概念上讲,您正在尝试根据学生的 ID 在两个数据集之间进行连接。我不认为 lodash 有一个 sql-esque 连接,所以在没有它的情况下你可以像下面那样做简单的 O(n^2) 实现。
var new_students = _.map(students, function(stud){
var matching_score = _.chain(marks).filter(function(mark){
return stud.sID == mark.lab.sID;
})
.first()
.value();
var new_student = _.cloneDeep(stud);
new_student.coding = matching_score.coding;
return new_student;
});
请注意此 returns new 学生对象并且不会改变您的旧对象。也就是说,如果您关心性能并且不介意可变性,那么进行哈希连接将使您获得 O(n) 性能。
var sqljoin = function(first, second, first_on, second_on, item_maker){
var first_dict = {};
_.each(first, function(f){
var key = first_on(f);
if(! (key in first_dict) ){
first_dict[key] = f;
}
});
return _.chain(second).filter(function(s){
var key = second_on(s);
return key in first_dict;
})
.map(function(s){
var key = second_on(s);
var first_val = first_dict[key];
var second_val = s;
return item_maker(first_val, second_val);
})
.value();
};
_.mixin('sqljoin', sqljoin);
您可以通过 sID
使用 keyBy() to serve as reference. Use map to return a new array of students wherein it uses pick to get the keys that you want from the marks.lab
cache, and then use assign() 添加所有学生属性来缓存 marks.lab
数组。这样做可以确保 students
数组不会发生变异。
var labs = _.keyBy(marks.lab, 'sID'); // cache by key
var result = _.map(students, function(student) {
return _(labs[student.sID]) // get the cache
.pick(['coding']) // This returns a new object
.assign(student); // Assigns the student object
});
var students = [
{ sID: '1', name: 'Ryan' },
{ sID: '2', name: 'Rez James' },
{ sID: '3', name: 'Hazel Charmagne' }
];
var marks = {
lab: [
{ sID: '1', coding: 'A' },
{ sID: '2', coding: 'A' },
{ sID: '3', coding: 'A' }
]
};
var labs = _.keyBy(marks.lab, 'sID'); // cache by key
var result = _.map(students, function(student) {
return _(labs[student.sID]) // get the cache
.pick(['coding']) // This returns an immutable object
.assign(student); // Assigns the student object
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>
更新
对于 lodash 3 的解决方案,您可以简单地更改 lodash 4 的 keyBy() with lodash 3's indexBy().
var labs = _.indexBy(marks.lab, 'sID'); // cache by key
var result = _.map(students, function(student) {
return _(labs[student.sID]) // get the cache
.pick(['coding']) // This returns an immutable object
.assign(student); // Assigns the student object
});
var students = [
{ sID: '1', name: 'Ryan' },
{ sID: '2', name: 'Rez James' },
{ sID: '3', name: 'Hazel Charmagne' }
];
var marks = {
lab: [
{ sID: '1', coding: 'A' },
{ sID: '2', coding: 'A' },
{ sID: '3', coding: 'A' }
]
};
var labs = _.indexBy(marks.lab, 'sID'); // cache by key
var result = _.map(students, function(student) {
return _(labs[student.sID]) // get the cache
.pick(['coding']) // This returns an immutable object
.assign(student); // Assigns the student object
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdn.jsdelivr.net/lodash/3.10.1/lodash.js"></script>
使用lodash的优势是它提供了一些已经预先编写好的实用方法,可以节省资源和开发人员创建函数的时间。至于你的 for
循环解决方案的情况,你可能会说在更简单的情况下,一个简单的 for
循环比使用 lodash
实用方法更好和可读。
如果我们谈论性能,您可能会说在解决方案方面,您的 for
循环可能会影响性能,因为它是 O(N^2 ).您可能会创建一个 for
循环版本来缓存 marks.lab
数组,然后再次循环 students
数组以获得正确的输出:
var labs = {};
var i;
for(i = 0; i < marks.lab.length; i++) {
labs[marks.lab[i].sID] = marks.lab.coding;
}
for(i = 0; i < students.length; i++) {
students[i].coding = labs[students[i].sID];
}
上面的解决方案对于两个循环都有一个 O(N)。除了您的 for
循环解决方案和上面的 for
循环解决方案改变原始 students
数组的部分外,它更接近我上面提供的解决方案。当您想重用原始数组 可以 是一件坏事。让我们调整上面的 for
循环解决方案,以防止改变原始数组:
var labs = {};
var result = [];
var i;
for(i = 0; i < marks.lab.length; i++) {
labs[marks.lab[i].sID] = marks.lab.coding;
}
for(i = 0; i < students.length; i++) {
result.push(Object.assign(
{ coding: labs[students[i].sID] },
students[i]
));
}
如果您将上面的 for
循环解决方案与我提供的 lodash
解决方案进行比较,那么它肯定会为您节省几行代码和编写代码的时间。
我是 lodash 的新手,我想将这个使用 i 和 j 的 forloop 转换为 lodash,这样我的编码就减少了。
for(var i =0 ; i < students.length; i++){
for(var j = 0; j <marks.lab.length;j++){
if(students[i].sID === marks.lab[j].sID){
students[i].coding = data.lab[j].coding;
}
}
}
如果使用 lodash 还有其他优势,请告诉我。
从概念上讲,您正在尝试根据学生的 ID 在两个数据集之间进行连接。我不认为 lodash 有一个 sql-esque 连接,所以在没有它的情况下你可以像下面那样做简单的 O(n^2) 实现。
var new_students = _.map(students, function(stud){
var matching_score = _.chain(marks).filter(function(mark){
return stud.sID == mark.lab.sID;
})
.first()
.value();
var new_student = _.cloneDeep(stud);
new_student.coding = matching_score.coding;
return new_student;
});
请注意此 returns new 学生对象并且不会改变您的旧对象。也就是说,如果您关心性能并且不介意可变性,那么进行哈希连接将使您获得 O(n) 性能。
var sqljoin = function(first, second, first_on, second_on, item_maker){
var first_dict = {};
_.each(first, function(f){
var key = first_on(f);
if(! (key in first_dict) ){
first_dict[key] = f;
}
});
return _.chain(second).filter(function(s){
var key = second_on(s);
return key in first_dict;
})
.map(function(s){
var key = second_on(s);
var first_val = first_dict[key];
var second_val = s;
return item_maker(first_val, second_val);
})
.value();
};
_.mixin('sqljoin', sqljoin);
您可以通过 sID
使用 keyBy() to serve as reference. Use map to return a new array of students wherein it uses pick to get the keys that you want from the marks.lab
cache, and then use assign() 添加所有学生属性来缓存 marks.lab
数组。这样做可以确保 students
数组不会发生变异。
var labs = _.keyBy(marks.lab, 'sID'); // cache by key
var result = _.map(students, function(student) {
return _(labs[student.sID]) // get the cache
.pick(['coding']) // This returns a new object
.assign(student); // Assigns the student object
});
var students = [
{ sID: '1', name: 'Ryan' },
{ sID: '2', name: 'Rez James' },
{ sID: '3', name: 'Hazel Charmagne' }
];
var marks = {
lab: [
{ sID: '1', coding: 'A' },
{ sID: '2', coding: 'A' },
{ sID: '3', coding: 'A' }
]
};
var labs = _.keyBy(marks.lab, 'sID'); // cache by key
var result = _.map(students, function(student) {
return _(labs[student.sID]) // get the cache
.pick(['coding']) // This returns an immutable object
.assign(student); // Assigns the student object
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>
更新
对于 lodash 3 的解决方案,您可以简单地更改 lodash 4 的 keyBy() with lodash 3's indexBy().
var labs = _.indexBy(marks.lab, 'sID'); // cache by key
var result = _.map(students, function(student) {
return _(labs[student.sID]) // get the cache
.pick(['coding']) // This returns an immutable object
.assign(student); // Assigns the student object
});
var students = [
{ sID: '1', name: 'Ryan' },
{ sID: '2', name: 'Rez James' },
{ sID: '3', name: 'Hazel Charmagne' }
];
var marks = {
lab: [
{ sID: '1', coding: 'A' },
{ sID: '2', coding: 'A' },
{ sID: '3', coding: 'A' }
]
};
var labs = _.indexBy(marks.lab, 'sID'); // cache by key
var result = _.map(students, function(student) {
return _(labs[student.sID]) // get the cache
.pick(['coding']) // This returns an immutable object
.assign(student); // Assigns the student object
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdn.jsdelivr.net/lodash/3.10.1/lodash.js"></script>
使用lodash的优势是它提供了一些已经预先编写好的实用方法,可以节省资源和开发人员创建函数的时间。至于你的 for
循环解决方案的情况,你可能会说在更简单的情况下,一个简单的 for
循环比使用 lodash
实用方法更好和可读。
如果我们谈论性能,您可能会说在解决方案方面,您的 for
循环可能会影响性能,因为它是 O(N^2 ).您可能会创建一个 for
循环版本来缓存 marks.lab
数组,然后再次循环 students
数组以获得正确的输出:
var labs = {};
var i;
for(i = 0; i < marks.lab.length; i++) {
labs[marks.lab[i].sID] = marks.lab.coding;
}
for(i = 0; i < students.length; i++) {
students[i].coding = labs[students[i].sID];
}
上面的解决方案对于两个循环都有一个 O(N)。除了您的 for
循环解决方案和上面的 for
循环解决方案改变原始 students
数组的部分外,它更接近我上面提供的解决方案。当您想重用原始数组 可以 是一件坏事。让我们调整上面的 for
循环解决方案,以防止改变原始数组:
var labs = {};
var result = [];
var i;
for(i = 0; i < marks.lab.length; i++) {
labs[marks.lab[i].sID] = marks.lab.coding;
}
for(i = 0; i < students.length; i++) {
result.push(Object.assign(
{ coding: labs[students[i].sID] },
students[i]
));
}
如果您将上面的 for
循环解决方案与我提供的 lodash
解决方案进行比较,那么它肯定会为您节省几行代码和编写代码的时间。