问题描述
我对 Javascript 有点陌生,所以我会尽力解释这一点。我在 fizz buzz 循环中使用了 vanilla JS,但我想我尝试的做法略有不同。
我已将两组数字放在 2 个单独的数组中,并通过 for
循环成功地通过计数到 20,但我没有使用数组来执行此操作。但是,我想使用作为参数传递的变量来检查值是否为真,以便可以打印适当的响应,无论是 fizz、buzz 还是 fizzbuzz。
我的 for
循环代码是:
const fizz = [3,6,9,12,15,18];
const buzz = [5,10,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 of
和 forEach
,但我也在苦苦思索如何编写这些代码。
我知道这很麻烦,但我如何编写 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,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 === 0
和 isBuzz = n => n%5 === 0
,并获得线性时间复杂度。
你可以这样做...
const
fizz = [3,18],buzz = [5,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}
你介意解释一下吗?
@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(...)
返回一个新数组
女巫被 arr.sort(...)
使用并返回一个引用到同一个数组“已排序”arr.forEach(...)
sort
方法使用 Arrow function expressions
arr.sort((a,b)=>a-b)
等于
arr.sort( function(a,b) { return a-b } )
Array.forEach()
也使用箭头函数表达式,
他的内部函数可以接受 3 个参数:
~ 当前循环元素,
~他的索引,
~ 对原始数组的引用(在链式操作中很有用;就像这里)
此处对原始数组的引用经过转换以返回元素 i + 1
的值,通过操作 { [i + 1] : n }
,在名为 n
的变量中(对于 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()
如果你真的需要获取中间值
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-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}
布尔值:
在简单的相等测试的情况下,Array.includes()
比 Array.some()
更快且更可取
和
一个简单的数组引用,如果比 if
console.time('speed test')
const
fizz = [3,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,18] },{ buzz: [ 5,20 ] },{ zazz: [ 1,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,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,buzz: [5,zazz: [1,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(' '));
});