JavaScript FIzzBuzz 使用类似于 Swift 的模式匹配的元组

JavaScript FIzzBuzz using Tuples similar to Swift's pattern matching

我想要实现的是 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 
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, true],
        () => console.log("Buzz")
      ],
      [[false, false],
        () => 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):
        //...
  }