使用lodash而不是forloop

时间:2016-05-23 02:51:42

标签: angularjs 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还有其他任何优点,请告诉我。

2 个答案:

答案 0 :(得分:2)

您可以使用keyBy()marks.lab缓存sID数组作为参考。使用map返回一个新的学生数组,其中使用pickmarks.lab缓存中获取所需的密钥,然后使用assign()添加所有学生财产。这样做可以确保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
});

&#13;
&#13;
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>');
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>
&#13;
&#13;
&#13;

<强>更新

对于lodash 3解决方案,您只需使用lodash 3&#39; s keyBy()更改lodash 4 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
});

&#13;
&#13;
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>');
&#13;
<script src="https://cdn.jsdelivr.net/lodash/3.10.1/lodash.js"></script>
&#13;
&#13;
&#13;

使用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解决方案进行比较,那么它肯定会为你节省几行和编码时间。

答案 1 :(得分:1)

从概念上讲,您正尝试根据学生的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;
    });

请注意,这会返回学生对象,并且不会改变您的旧对象。也就是说,如果你关心性能并且不介意可变性,那么进行散列连接将获得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);