首页 > 解决方案 > 如果我的字符串测试函数的输入为空,则返回 false

问题描述

我正在做一个问题集来查找"x"and的出现次数"o",不区分大小写,如果它们在字符串中出现的次数相同,则返回 true,否则返回 false。问题集有几个边缘情况,其中一些我已经解决了,但是这个边缘情况仍然存在。

Empty string contains equal amount of x and o - Expected: true, instead got: false

这是代码:

function XO(str) {
    //code here

    var res_x = str.match(/x/gi)
    var res_o = str.match(/o/gi)
    if (res_o !== null && res_x !== null) 
    {
      res = (res_o.length) == (res_x.length)?true:false

    } else if (res_o == "" || res_x == "") {

      res = true

    } else if (res_o == "" && res_x == "") {

      res = true

    } else if (res_o == null && res_x == null) {
        res = false
    } else {

      res = false

    }



    return res

}

标签: javascriptstringalgorithm

解决方案


这里的逻辑过于复杂。过多的分支和布尔值使程序难以理解。边缘情况几乎是虚构的——空字符串不需要来自较长字符串的任何特殊逻辑。

这是一种可能的方法:从字符串中删除所有"x"字符并获取长度。从字符串中删除所有"o"字符并获取长度。如果删除后的长度相同,则返回 true。空字符串将被处理,因为"".length === "".length.

const xo = s => s.replace(/x/gi, "").length === s.replace(/o/gi, "").length;

[
  "",
  "xo",
  "oxox",
  "xxoo",
  "xoo",
  "oxx",
  "x",
  "o",
  "oxxox"
].forEach(e => console.log(xo(e)));

检查null不是在 JS 中通常完成的事情——如果调用者通过做一些愚蠢的事情(比如用无意义的值调用函数)破坏(隐式)合同,您可以简单地让异常抛出。

如果你必须这样做,你可以使用try/ catch

const xo = s => {
  try {
    return s.replace(/x/gi, "").length === s.replace(/o/gi, "").length;
  }
  catch {
    return false;
  }
};

[  
  42,
  {},
  [],
  null,
  undefined,
  "",
  "xo",
  "oxox",
  "xxoo",
  "xoo",
  "oxx",
  "x",
  "o",
  "oxxox"
].forEach(e => console.log(xo(e)));

可能还值得考虑的是,这个函数可以/应该被概括为接受任何字符作为参数,而不是硬编码它只在"x"和上工作"o"。就像是:

const balanced = s => {
  const frequencies = Object.values([...s].reduce((a, e) => {
    a[e] = ++a[e] || 1;
    return a;
  }, {}));
  return frequencies.every(e => e === frequencies[0]);
};

[  
  "",
  "xo",
  "oxox",
  "xxoo",
  "abc",
  "acbd",
  "x",
  "o"
].forEach(e => console.log(balanced(e)));


推荐阅读