使用Tuples的JavaScript FIzzBuzz与Swift的模式匹配类似

问题描述

我要实现的是FizzBu​​zz的模式匹配版本。 类似于Swift中仅使用JavaScript的版本。

如果一个数字可被3 console.log Fizz整除,如果被5整除,则Buzz如果被两个FizzBu​​zz整除,则两者都不记录。 我面临的挑战是:

function fizzBuzz(numbers) {
  for (number in numbers) {
    let div3 = number % 3 == 0 ? true : false;
    let div5 = number % 5 == 0 ? true : false;
     
    switch ([div3,div5]) {
      case [true,true]:
        console.log("FizzBuzz");
        break;
      case [true,false]:
        console.log("Fizz");
        break;
      case [false,true]:
        console.log("Buzz");
        break;
      case [false,false]: 
        console.log(number);
            break;
    }
  }
}

var array = [...Array(100).keys()];

fizzBuzz(array);

这不起作用,我尝试没有方括号,但是只有第一个变量被求值,而另一个变量被忽略。有人可以帮我一下吗? 在Swift中,这非常简单,并且可以完美地工作,我正在尝试在JS中实现同样的效果

我尝试了这个,但是像上面提到的那样,只求方括号中的第一个变量div3,div5被完全忽略:

function fizzBuzz(numbers) {
  for (number in numbers) {
    let div3 = number % 3 == 0 ? true : false;
    let div5 = number % 5 == 0 ? true : false;
     
    switch (div3,div5) {
      case (true,true):
        console.log("FizzBuzz");
        break;
      case (true,false):
        console.log("Fizz");
        break;
      case (false,true):
        console.log("Buzz");
        break;
      case (false,false): 
        console.log(number);
            break;
    }
  }
}

var array = [...Array(100).keys()];

fizzBuzz(array);

我甚至想在JS中实现这样的语法吗?

解决方法

不确定这是否是愚蠢的方法:

const case_signature = (...args) => JSON.stringify(args);

function fizzBuzz(numbers) {
  for (number in numbers) {
    let div3 = number % 3 === 0;
    let div5 = number % 5 === 0;
     
    switch (case_signature(div3,div5)) {
      case case_signature(true,true):
        console.log("FizzBuzz");
        break;
      case case_signature(true,false):
        console.log("Fizz");
        break;
      case case_signature(false,true):
        console.log("Buzz");
        break;
      case case_signature(false,false): 
        console.log(number);
            break;
    }
  }
}

var array = [...Array(100).keys()];

fizzBuzz(array);

另一种方式(但不确定是否满足您的要求):

const multi_mod = (number,...divisors) =>
  number % divisors.reduce((acc,div) => acc = acc * div,1);

function fizzBuzz(numbers) {
  for (number in numbers) {
    switch (0) {
      case multi_mod(number,3,5):
        console.log("FizzBuzz");
        break;
      case multi_mod(number,3):
        console.log("Fizz");
        break;
      case multi_mod(number,5):
        console.log("Buzz");
        break;
      default: 
        console.log(number);
    }
  }
}

var array = [...Array(100).keys()];

fizzBuzz(array);

我真的不知道什么是元组,但是也许这有点像您的原始问题:

// array_equal borrowed from https://stackoverflow.com/a/19746771/14454939
const array_equal = (array1,array2) =>
  array1.length === array2.length && array1.every((value,index) => value === array2[index]);

const switch_tuple = (compare) => (...cases) => {
  for (let i = 0; i < cases.length; i++) {
    const result = array_equal(compare,cases[i][0]);
    if (result) {
      cases[i][1]();
      return result;
    }
  }
};

function fizzBuzz(numbers) {
  for (number in numbers) {
    let div3 = number % 3 == 0 ? true : false;
    let div5 = number % 5 == 0 ? true : false;

    switch_tuple([div3,div5])(
      [[true,true],() => console.log("FizzBuzz")
      ],[[true,false],() => console.log("Fizz")
      ],[[false,() => console.log("Buzz")
      ],() => console.log(number)
      ],)
  }
}

var array = [...Array(100).keys()];

fizzBuzz(array);

,

switch/case使用===运算符比较值。这是通过标识而不是内容来比较数组,因此您不能像尝试过的那样将其与数组文字一起使用。

JavaScript没有元组。 div3,div5使用comma operator,它只是将其评估为div5的值。

如果您想要类似您的编码模式的内容,我认为您可以做的最好的就是使用JSON。

function fizzBuzz(numbers) {
  for (number in numbers) {
    let div3 = number % 3 == 0 ? true : false;
    let div5 = number % 5 == 0 ? true : false;
     
    switch (JSON.stringify([div3,div5])) {
      case '[true,true]':
        console.log("FizzBuzz");
        break;
      case '[true,false]':
        console.log("Fizz");
        break;
      case '[false,true]':
        console.log("Buzz");
        break;
      case '[false,false]': 
        console.log(number);
            break;
    }
  }
}

var array = [...Array(100).keys()];

fizzBuzz(array);

,

您还可以将布尔数组转换为数字,然后将其用于打开:

  const pattern = (...args) => args.reduce((s,n,i) => s + n << i,0);

  switch(pattern(true,false)) {
     case pattern(false,false):
        //...
  }