Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/460.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript array.reduce通过递归实现_Javascript_Algorithm - Fatal编程技术网

Javascript array.reduce通过递归实现

Javascript array.reduce通过递归实现,javascript,algorithm,Javascript,Algorithm,我正在尝试通过递归实现Array.reduce()方法,它适合我 var指数=0; 功能减少(arr、fn、初始){ 如果(索引>=arr.length){ 返回首字母; } 如果(!首字母){ 初始=arr[索引]; 索引++; } 初始值=fn(初始值,arr[索引],索引,arr); 索引++; 返回减少(arr、fn、初始); }一种可能的解决方案是将实际索引放入函数参数中,并检查数组中是否存在索引 要进一步查找初始值,需要一个未定义值的符号,以便在未定义值和未设置值之间进行区分 函

我正在尝试通过递归实现Array.reduce()方法,它适合我

var指数=0;
功能减少(arr、fn、初始){
如果(索引>=arr.length){
返回首字母;
}
如果(!首字母){
初始=arr[索引];
索引++;
}
初始值=fn(初始值,arr[索引],索引,arr);
索引++;
返回减少(arr、fn、初始);

}
一种可能的解决方案是将实际索引放入函数参数中,并检查数组中是否存在索引

要进一步查找
初始值
,需要一个未定义值的符号,以便在未定义值和未设置值之间进行区分

函数reduce(数组、fn、初始值、索引){
指数=指数| | 0;
if(arguments.length==0){
抛出“减少:无阵列”;
}
if(arguments.length==1 | | typeof fn!=='function'){
抛出“减少:无功能”;
}
if(arguments.length==2){
while(索引=array.length){
返回初始值;
}
返回reduce(数组,fn,数组中的索引?fn(初始值,数组[索引],索引,数组):初始值,索引+1);
}
//console.log(reduce());//投掷减少:没有阵列
//console.log(reduce([]);//抛出:没有函数
//log(reduce([],(a,b)=>a+b));//抛出减少:没有初始值的空数组
log(reduce([],(a,b)=>a+b,42));

log(reduce([3,4],(a,b)=>a+b))正如您所发现的,将索引参数放置在函数外部会导致复杂化,即必须持续管理索引参数才能使函数工作。我认为,通常情况下,编写函数的赋值假定它们是自包含的,而不是依赖于全局变量

我们可以像这样递归地概念化
reduce

功能减少(arr、fn、初始){
如果(!arr.length)
返回首字母;
如果(arr.length==1)
返回fn(首字母,arr[0]);
返回减少(arr.slice(1),fn,fn(初始值,arr[0]);
}
log(reduce([1,2,3],(a,b)=>a+b,0));//6.
在JavaScript中,对
slice
的每次调用都会生成该数组部分的副本,这使得该版本对于较大的输入效率较低。提高效率的一个选择是使用一个内部递归函数,该函数依赖于两个参数,一个索引和一个累加器,它将遍历数组,但我不确定验证器是否会允许它,因为外部函数将不再调用自身

在代码中还有一件事需要注意,
!只要
initial
是一个计算结果为“falsy”的值,而不仅仅是当它没有作为参数传入时,initial
就会捕获

这是一个“黑客”式的解决方案(因为它修改了
fn
,尽管我们可以将其修改回:),基于索引的解决方案不需要额外的参数,并且使用了
fn
的全部4个参数:

功能减少(arr、fn、初始){
如果(fn.index==未定义)
fn.index=0;
其他的
fn.index++;
如果(fn.index==arr.length)
返回首字母;
收益减少(arr,fn,fn(初始,arr[fn.index],fn.index,arr));
}
log(reduce([1,2,3],(a,b)=>a+b,0));//6.
一些问题:

  • 您将
    index
    定义为一个全局变量,该变量永远不会重置为0,因此如果多次调用
    reduce
    ,它将具有错误的值。有几种解决方案。我建议使用
    this
    值来跟踪您的位置
  • initial
    参数是可选的,但是您的代码使用
    来测试它!initial
    不够好:如果
    initial
    的值为0或任何其他错误值,则不应将其视为不存在。改为使用
    参数.length
  • 如果由于未提供
    initial
    参数而增加索引,则不会检查该索引是否变得过大。不应使用无效索引调用回调函数。交换两个
    if
    语句
  • 当传递的空数组没有初始值时,
    reduce
    返回
    undefined
    ,但它应该抛出一个错误,就像本机
    reduce
    方法一样
  • 当数组有“间隙”(即,它是一个稀疏数组)时,该函数仍会对缺少的索引调用回调函数。相反,不应该迭代那些不存在的条目。您可以通过使用数组迭代器来实现这一点,该迭代器只生成有效的索引
以下是您如何处理这些问题:

功能减少(arr、fn、初始){
//从“this”获取索引的迭代器。
//第一次它将不是迭代器,因此从arr.keys()获取它。
const iter=Object(this).next?this:arr.keys();
设item=iter.next();
if(arguments.length<3){//检查是否存在初始参数
//无需减少时抛出错误
如果(项目完成){
抛出新的TypeError(“减少没有初始值的空数组”);
}
初始=arr[项目价值];
item=iter.next();
}
//只有在处理了缺少的初始值之后,才检查数组的结尾
如果(项目完成)返回首字母;
初始值=fn(初始值,arr[项目价值],项目价值,arr);
return reduce.call(iter、arr、fn、initial);//通过`this'传递索引`
}
//一些测试用例
log(reduce([1,2,3],(a,b)=>a+b,0),“应该是6”);
log(reduce([1,2,3],(a,b)=>a+b,0),“应该是