如何重新创建Underscore.js _.reduce方法? [英] How to re-create Underscore.js _.reduce method?

查看:103
本文介绍了如何重新创建Underscore.js _.reduce方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于教育目的,我试图重新创建Underscore.js的 _。reduce()方法。虽然我可以使用for循环以明确的样式进行此操作。但是这远非理想,因为它改变了作为参数提供的原始列表,这是危险的。

我也意识到使用函数式编程风格创建这种方法是因为无法为循环显式设置 i 值,所以更难。

  //显式样式
var reduce = function(list,iteratee,initial){
if(Array.isArray(list)){
var start;
if(arguments.length === 3){
start = initial;
for(var i = 0; i< list.length; i ++){
start = iteratee(start,list [i],i);
}
} else {
start = list [0];
for(var i = 1; i< list.length; i ++){
start = iteratee(start,list [i],i);



if(list.constructor === Object){
var start;
if(arguments.length === 3){
start = initial;
for(var key in list){
start = iteratee(start,list [key],key);
}
} else {
start = list [Object.keys(list)[0]];

//删除第一个属性以避免重复。
delete list [Object.keys(list)[0]];
for(var key in list){
start = iteratee(start,list [key],key);
}
}
}

return start;
};

当我的 reduce()提供了一个参数, initial ,我需要随后跳过或移除第一个元素属性的参数, list 作为将返回的最终值。因为不这样做会重复计算第一个元素/属性。每个()或 forEach()函数都可以用函数式编程风格创建函数,



这是我的 reduce() 。它在提供 memo (初始值)时正常工作,因为我不需要跳过第一个元素/属性。但是当没有提供备忘录时,它不能正常工作,因为那么我将备忘录设置为第一个元素或属性,并且我应该可以在循环过程中跳过它,而我不知道如何。

  //函数样式(没有备忘录时不工作)
var reduce =函数(list,iteratee,memo){
var备忘录=备忘录||列表[0] ||列表[Object.keys(列表)[0]]。
_each(list,function(element,index,list){
memo = iteratee(memo,element,index,list);
});
返回备忘录;
};

我花了很长时间在Google上搜索我的问题的答案。但无法找到一个。我真的很感谢你的建议。感谢。



最后,这是一个额外的代码,我认为这是行不通的,但我认为它应该。

  var reduce = function(list,iteratee,memo){
var collection = list;
var accum;

_each(collection,function(item){
if(arguments.length< 3){
if(Array.isArray(collection)){
accumulate = collection [0];
collection.shift();
accumulate = iteratee(accumulate,item);
} else {
accumulation = collection [Object.keys( );
删除集合[Object.keys(collection)[0]];
accumulate = iteratee(accumulate,item);
}
} else {
accumulation =备忘录;
accumulate = iteratee(accumulate,item);
}
});

回报积累;
};


解决方案

这是我能想出的最短版本。

  _。reduce = function(list,iteratee,memo){
var memoUndefined = arguments.length< 3;
_each(list,function(elem,index,list){
if(memoUndefined){
memoUndefined = false;
memo = elem;
} else备忘录= iteratee(备忘录,元素,索引,列表);
});
返回备忘录;
};


For education purposes, I was trying to re-create Underscore.js's _.reduce() method. While I was able to do this in an explicit style using for loops. But this is far from ideal because it mutates the original list that was supplied as an argument, which is dangerous.

I also realized that creating such method using functional programming style is harder, since it is not possible to explicitly set i value for looping.

// Explicit style
var reduce = function(list, iteratee, initial) {
if (Array.isArray(list)) {
    var start;
    if (arguments.length === 3) {
        start = initial;
        for (var i = 0; i < list.length; i++) {
            start = iteratee(start, list[i], i);
        }
    } else {
        start = list[0];
        for (var i = 1; i < list.length; i++) {
            start = iteratee(start, list[i], i);
        }
    }
}
if (list.constructor === Object) {
    var start;
    if (arguments.length === 3) {
        start = initial;
        for (var key in list) {
            start = iteratee(start, list[key], key);
        }
    } else {
        start = list[Object.keys(list)[0]];

        // Delete the first property to avoid duplication.
        delete list[Object.keys(list)[0]];
        for (var key in list) {
            start = iteratee(start, list[key], key);
        }
    }
}

return start;
};

What makes me struggle is that when my reduce() is supplied with an argument, initial, I need to subsequently either skip or remove the first element or property of the argument, list for the final value that will be returned. Because not doing so will double count the first element/property. I can't think of how I could do such thing when creating the function with functional programming style, with _.each() or forEach() involved.

This is my functional style of reduce() that is working partially. It works correctly when memo(initial value) is supplied, because I don't need to skip the first element/property. But it's not working correctly when memo is not supplied, because then I'm setting memo to either first element or property, and I should be able to skip it during the looping, which I don't know how.

// Functional style (not working without memo)
var reduce = function(list, iteratee, memo) {
    var memo = memo || list[0] || list[Object.keys(list)[0]];
    _.each(list, function(element, index, list){
        memo = iteratee(memo, element, index, list);
    });
    return memo;
};

I spent quite a long time searching for answers to my question on Google. But wasn't able to find one. I would really appreciate your advice. Thanks.

Lastly, this is an additional code I came up with which does not work, but I think it should.

var reduce = function(list, iteratee, memo) {
    var collection = list;
    var accumulation;

    _.each(collection, function(item){
        if (arguments.length < 3) {
            if (Array.isArray(collection)) {
                accumulation = collection[0];
                collection.shift();
                accumulation = iteratee(accumulation, item);
            } else {
                accumulation = collection[Object.keys(collection)[0]];
                delete collection[Object.keys(collection)[0]];
                accumulation = iteratee(accumulation, item);
            }
        } else {
            accumulation = memo;
            accumulation = iteratee(accumulation, item);
        }
    });

    return accumulation;
};

解决方案

Here is the shortest version I could come up with.

_.reduce = function(list, iteratee, memo){
  var memoUndefined = arguments.length < 3;
  _.each(list, function(elem, index, list){
    if(memoUndefined) {
      memoUndefined = false;
      memo = elem;
    } else memo = iteratee(memo, elem, index, list);
  });
  return memo;
};

这篇关于如何重新创建Underscore.js _.reduce方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆