测试在Javascript中使用reduce时是否达到数组的最后一项

问题描述

我正在尝试使用.join()来实现.reduce()的等效功能,以回答关于executeprogram.com的测验。我的代码通过了测试,但是看起来很丑。我以丑陋的方式解决的特定问题是:构造的join()函数使用数组和分隔符作为参数,但是在构造结果联接时,不应在数组的最后一项之后插入分隔符输出。这意味着,当我使用reduce()遍历数组时,我是否必须测试 ,我是否位于最后一项(以便可以跳过使用分隔符)? [oops:see注意以下] 。如果数组中有重复的值,则无法使用indexOflastIndexOf。所以我创建了一个柜台。我不喜欢我希望提出有关如何更好地做到这一点的建议。这是代码

 function join(arr,separator) {
  let counter = 0;
  if (arr.length === 0) { return(''); }
  else { 
    return (
    arr.reduce((accumulator,item) =>
      {
        if (counter === arr.length - 1) {
          return accumulator + item;
        } else {
          counter += 1; 
          return accumulator + item + separator;
        }
      },'')
    );
  }
} 

测试及其预期输出如下。同样,上面的功能通过了所有测试,但是我认为必须有更好的方法

> join(['a'],',')
Expected: 'a'
> join(['a','b'],')
Expected: 'a,b' 
> join(['a','b','c'],'')
Expected: 'abc'
> join(['a','c','d'],'x')
Expected: 'axbxcxd'
> join(['a','COMMA')
Expected: 'aCOMMAb'
> join(['','',''],')
Expected: ','
> join([],')
Expected: ''

注意:看到所有有用的答案后,我意识到造成此丑陋代码 real 原因是我错误地认为分隔符位于项目“之后”。实际上,分隔符位于项目之间 之间,如果您在除第一个项目之外的所有项目之前插入分隔符,则可以使它位于项目之间 。然后,您无需测试最后一项。当您删除需要测试最后一项的假设时,一切都变得简单得多。因此,基本上,我首先说的是错误的问题。感谢大家的回答!

解决方法

正如其他人指出的那样,您可以在回调中使用索引和数组args。

但是还有另一种方法。您不必知道何时遇到最后一个数组元素。您已经知道第一个元素是什么,就可以使用它。

const join = (arr,sep=',') => arr.slice(1).reduce((acc,item) => acc + sep + item,arr[0]);

要进一步完善该功能,请利用很少使用的累加器默认初始值。如果您没有将初始值传递给reduce()函数,则将在数组的第一和第二个元素的第一个执行回调。

const join = (arr,') => arr.reduce((acc,item) => acc + sep + item);

要处理空数组而没有错误...

const join = (arr,') => arr[0] ? arr.reduce((acc,item) => acc + sep + item) : '';
,

reduce回调通过4个参数调用:

arr.reduce(callback( accumulator,currentValue,index,array)

示例:

function join(arr,separator) {
  if (arr.length === 0) { return(''); }
  
  else { 
    return (
    arr.reduce((accumulator,item,counter) =>
      {
        if (counter === arr.length - 1) {
          return accumulator + item;
        } else {
          counter += 1; 
          return accumulator + item + separator;
        }
      },'')
    );
  }
}
    
    
console.log(join(['a'],','))
console.log(join(['a','b'],'b','c'],''))
console.log(join(['a','c','d'],'x'))
console.log(join(['a','COMMA'))
console.log(join(['','',''],'))
console.log(join([],'))

您可以通过以下方式将代码缩短一点:

  1. 跳过空检查-如果数组为空,则reduce将返回初始值('')。
  2. 使用模板字符串和三进制。如果不是最后一项,请添加分隔符;如果是,请使用空字符串。
  3. 由于计数器(i)以0开头,因此您可以跳过第一项的分隔符(将0强制转换为false)。这样,您就可以跳过三元比较。

const join = (arr,separator) => arr.reduce((accumulator,i) =>
  `${accumulator}${i ? separator : ''}${item}`,'')
    
    
console.log(join(['a'],'))

更改顺序时的另一种想法(基于@JCFord arr[0]想法)是对数组进行解构,采用第一个元素(first),如果为空则为其分配默认值。然后减少数组的其余部分,并使用first作为初始值。

const join = ([first = '',...arr],separator) => 
  arr.reduce((accumulator,i) => `${accumulator}${separator}${item}`,first)
    
    
console.log(join(['a'],'))

,

您可以通过从reduce中删除初始值来简化当前功能。然后,它将使用第一个元素作为初始值。您已经设置了guard子句来处理空数组,因此在这方面应该没问题。

function join(arr,separator) {
  if (arr.length == 0) return '';
  return arr.reduce((accumulator,item) => accumulator + separator + item);
}

console.log(join(['a'],'))

使用join reduce字符串数组的另一种简便方法是,根本不关心它产生的附加分隔符,而在缩小数组后slice将其关闭。 >

function join(arr,separator) {
  return arr.reduce((accumulator,item) => accumulator + separator + item,'')
            .slice(separator.length);
}

console.log(join(['a'],'))