如何使用 for、for of 或 forEach 循环遍历 2 个数组作为参数

How to loop through 2 arrays as arguments with for, for of, or forEach

我对 Javascript 有点陌生,所以我会尽力正确解释这一点。我在 fizz buzz loop 上使用 vanilla JS,但我想我想稍微改变一下。

我已将两组数字放在 2 个单独的数组中,并通过 for 循环成功地计数到 20,但我没有使用数组来做到这一点。但是,我想使用作为参数传递的变量来检查值是否为真,以便可以打印适当的响应,fizz、buzz 或 fizzbuzz。

我的 for 循环代码是:

const fizz = [3, 6, 9, 12, 15, 18];
const buzz = [5, 10, 15, 20];

for (let i = 1; i <= 20; i++){
    if(i % 3 === 0 && i % 5 === 0) {
        console.log(i + " fizz buzz");
    } else if(i % 3 === 0){
       console.log(i + " fizz");
    } else if(i % 5 === 0) {
    console.log(i + " buzz");
    } else {
        console.log(i);
    }
}
.as-console-wrapper {max-height: 100%!important;top:0}

如我所说,运行成功。

我确实用 fizz 和 buzz 变量编辑了 for 循环,但没有成功。我尝试使用 index & indexOf,但我不确定如何编码。

我也使用了 for offorEach,但我也在为如何编写这些代码而苦苦挣扎。

我知道它很乱,但我的 forEach 方法编码方式如下所示:

fizz.forEach(function(value) {
     if (i === fizz.indexOf[value]) {
        console.log(value);
         i++;
     }
});

最终我对所有这些的问题是 - 我如何将这些数组作为参数传递以循环遍历并检查它们的值是否为真?而且,哪种方法最好?

您可以使用函数 some 测试您迭代的数字是否在任何数组中。例如,

const fizz = [3, 6, 9, 12, 15, 18];
const buzz = [5, 10, 15, 20];

for(let i = 1; i <= 20; i++){
    const isFizz = fizz.some(f => f === i);
    const isBuzz = buzz.some(b => b == i);
    if(isFizz && isBuzz){
        console.log(i + " fizz buzz");
    } else if(isFizz){
        console.log(i + " fizz");
    } else if(isBuzz){
        console.log(i + " buzz");
    } else {
        console.log(i);
    }
}

*注意:整体算法的性能高于线性,因为 some() 遍历数组并在 for 循环内。另一种方法是使isFizz = n => n%3 === 0isBuzz = n => n%5 === 0,并获得线性时间复杂度。

你可以做到...

const 
  fizz = [3, 6, 9, 12, 15, 18]
, buzz = [5, 10, 15, 20]
  ;
fizz.concat(buzz).sort((a,b)=>a-b).forEach((v,i,{[i+1]:n})=>
  {
  if (v!=n)
    console.log(v, !fizz.includes(v) ? 'buzz': buzz.includes(v) ? 'fizz buzz': 'fizz' ) 
  })
.as-console-wrapper {max-height: 100%!important;top:0}

Would you mind explaining it?
@KENAXION

javascript 语言允许使用方法和函数的链接
所以

fizz.concat(buzz).sort((a,b)=>a-b).forEach(...)

等同于

let arr = fizz.concat(buzz) // adding fizz buzz into new array ( named arr )
arr.sort((a,b)=>a-b)
arr.forEach(...)

在此链接中:
Array.concat(...) return 一个新数组
arr.sort(...) 和 return 引用到同一个数组“已排序”
arr.forEach(...)

使用

sort 方法使用 Arrow function expressions

arr.sort((a,b)=>a-b)

等于

arr.sort( function(a,b) { return a-b } )

Array.forEach()也使用了箭头函数表达式,
他的内部函数可以接受 3 个参数:
~ 当前循环元素,
~他的指数,
~ 对原始数组的引用(在链接操作中很有用;就像这里一样)

此处对原始数组的引用在名为 n 的变量中通过操作 { [i + 1] : n } 转换为 return 元素 i + 1 的值(对于 n分机)

故事:
在对 fizz 和 buzz 的拼接数组进行排序时,有些元素是重复的,排序后不可避免地会相互跟随。 在这里,忽略这些重复项的方法是检查处理后的元素是否与其下一个 if (v != n).

不同

然后 console.log 调用双三元测试

!fizz.includes(v) ? 'buzz': buzz.includes(v) ? 'fizz buzz': 'fizz'

可归纳如下:

if (!fizz.includes(v)      return 'buzz'
else if (buzz.includes(v)) return 'fizz buzz'
else                       return 'fizz'

文档链接:
Array.concat(), Array.sort(), Array.forEach(), Conditional (ternary) operator, Array.includes()

if you really need to get intermediate values

const arrs =
  { fizz : Array.from({length: 6},(_,i)=>(i+1)*3)
  , buzz : Array.from({length: 4},(_,i)=>(i+1)*5)
  , zazz : [ 1, 3, 5, 8 ]
  };

Object.values(arrs)
  .reduce((sum,arr)=>sum.concat(arr),[])
  .sort((a,b)=>a-b)
  .forEach((v,i,{[i-1]:p})=>
  {
  for(let n=(p??0)+1;n<v;++n) console.log(n)
  if (v!=p)
    console.log(v, Object.keys(arrs).filter((nm)=>arrs[nm].includes(v)).join(' ') ) 
  })
.as-console-wrapper {max-height: 100%!important;top:0}

A Boolean one:

在简单相等性测试的情况下,Array.includes()Array.some()
更快更可取 和
如果比 if

的级联速度快,则为简单数组引用

console.time('speed test')

const 
  fizz = [3, 6, 9, 12, 15, 18]
, buzz = [5, 10, 15, 20]
, txts = [ '', 'fizz', 'buzz', 'fizz buzz']
  ;
for (let i = 1; i <= 20; ++i ) 
  {
  let ref = fizz.includes(i) ? 1 : 0;
     ref |= buzz.includes(i) ? 2 : 0;
  console.log( i, txts[ref] )
  }

console.timeEnd('speed test')
.as-console-wrapper {max-height: 100%!important;top:0}

最后一个解决方案(4)

const arrs  =
  [ { fizz: [ 3, 6, 9, 12, 15, 18] }
  , { buzz: [ 5, 10, 15, 20 ] }
  , { zazz: [ 1, 3, 5, 8 ] }
  ]

showArrCom(arrs) 

function showArrCom(ArrList)
  {
  const
    arrN = ArrList.map(o=>Object.entries(o).reduce((r,[k,v])=>({n:k,i:0,a:v}),{}))
  , doLoop =_=> arrN.reduce((t,{a,i})=>t || (a[i]!=undefined), false)
    ;
  for (let indx=1; doLoop(); indx++ )
    {
    document.write( arrN.reduce((m,{n,a,i},x,t)=>
      {
      if (a[i]===indx) { m += `${n} `; t[x].i++ }
      return m
      }, `${indx} `) + '<br>')
    }
  }

我对你想要完成的事情有点困惑,但我想我明白了......你想检查给定的数字是否在数组之一中,对吗?

为此,您可以使用 .includes.indexOf

.includes 将检查该值是否存在于数组中,而 .indexOf 将为您提供数组中值的索引或 -1 如果它不存在。

此外,对于您所做的 .forEach 尝试。首先,您需要创建一个范围为 1 到 20 的数组。然后,使用与您已经构建的相同逻辑在创建的范围上应用 .forEach

考虑到这一点,您还可以扩展代码以添加多个数组。

const fizz = [3, 6, 9, 12, 15, 18];
const buzz = [5, 10, 15, 20];

// create range of number from X to Y
const createRange = (FROM, TO) => [...Array(TO - FROM + 1).keys()].map(i => i + FROM);

const values = createRange(1, 20);

console.log('using includes...');
values.forEach(i => {
    const isFizz = fizz.includes(i);
    const isBuzz = buzz.includes(i);
    if(isFizz && isBuzz) console.log(i + " fizz buzz");
    else if(isFizz) console.log(i + " fizz");
    else if(isBuzz) console.log(i + " buzz");
    else console.log(i);
});

console.log('using indexOf...');
values.forEach(i => {
    const isFizz = fizz.indexOf(i) !== -1;
    const isBuzz = buzz.indexOf(i) !== -1;
    if(isFizz && isBuzz) console.log(i + " fizz buzz");
    else if(isFizz) console.log(i + " fizz");
    else if(isBuzz) console.log(i + " buzz");
    else console.log(i);
});


const arrs = {
  fizz: [3, 6, 9, 12, 15, 18],
  buzz: [5, 10, 15, 20],
  zazz: [1, 3, 5, 8],
}

console.log('with multiple input arrays');
values.forEach(i => {
  const output = [i];
  Object.keys(arrs).forEach(key => {
    if (arrs[key].includes(i)) output.push(key);
  });
  
  console.log(output.join(' '));
});