【问题标题】:use lodash instead of forloop使用 lodash 代替 for 循环
【发布时间】:2016-05-23 02:51:41
【问题描述】:

我是 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 还有其他优势,请告诉我。

【问题讨论】:

    标签: angularjs lodash


    【解决方案1】:

    您可以通过sID 使用keyBy() 缓存marks.lab 数组作为参考。使用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
    });
    

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

    更新

    对于 lodash 3 解决方案,您可以简单地将 lodash 4 的 keyBy() 更改为 lodash 3 的 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>');
    &lt;script src="https://cdn.jsdelivr.net/lodash/3.10.1/lodash.js"&gt;&lt;/script&gt;

    使用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。但我的项目是 3.x 版。感谢您的解决方案。用 _.each 函数做的
    • 让我试试看。在我得到一个问题之前。如果我可以在两个简单的 for 循环中完成任务,那么在此处包含 lodash 有什么好处。
    • @AlaksandarJesusGene 检查 **advantage` 的更新。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-12
      • 1970-01-01
      • 2021-10-17
      • 2022-01-14
      • 2015-04-10
      • 2020-12-22
      • 2020-11-24
      相关资源
      最近更新 更多