【问题标题】:How to split a camelCase string and check if each split word is part of an array or not?如何拆分camelCase字符串并检查每个拆分词是否是数组的一部分?
【发布时间】:2019-06-21 21:05:44
【问题描述】:

假设我有一个 单词数组 和几个 camelCase 字符串,如下所示:

var arr = ["hello", "have", "a", "good", "day", "stackoverflow"];
var str1 = "whenTheDayAndNightCollides";
var str2 = "HaveAGoodDay";
var str3 = "itIsAwfullyColdDayToday";
var str4 = "HelloStackoverflow";

如何将camelCase 单词拆分为单独的字符串,将每个拆分字符串(转换为小写)与arr 数组元素进行比较,如果每个拆分字符串都是指定数组的一部分,则返回true

"whenTheDayAndNightCollides" // should return false since only the word "day" is in the array

"HaveAGoodDay" // should return true since all the words "Have", "A", "Good", "Day" are in the array

"itIsAwfullyColdDayToday" // should return false since only the word "day" is in the array

"HelloStackoverflow" // should return true since both words "Hello" and "Stackoverflow" are in the array

正如其他SO thread 中所建议的那样,我尝试使用every() 方法和indexOf() 方法来测试是否可以在数组中找到每个拆分字符串,如以下代码所示片段,但它不起作用:

var arr = ["hello", "have", "a", "good", "day", "stackoverflow"];

function checkString(wordArray, str)
{
    // split the camelCase words
    var x = str.replace(/([A-Z])/g, ' $1').split(" ");

    return x.every(e => {
        return wordArray.indexOf(e.toLowerCase()) >= 0;
    });
}

console.log("should return true ->" + checkString(arr, "HelloStackoverflow"));
console.log("should return false ->" + checkString(arr, "itIsAwfullyColdDayToday"));

我做错了什么?

【问题讨论】:

    标签: javascript regex


    【解决方案1】:

    对于这种特殊情况,我将使用lookahead assertion(?=...),这是一个非捕获构造,我将直接与String::split() 方法一起使用。当字符串以大写字母开头时,这将解决数组上额外生成的empty string 元素的问题。我也会尝试Array::includes() 以换取indexOf()

    const arr = ["hello", "have", "a", "good", "day", "stackoverflow"];
    
    function checkString(wordArray, str)
    {
        return str.split(/(?=[A-Z])/g).every(
            e => wordArray.includes(e.toLowerCase())
        );
    }
    
    console.log(
        "checkString(arr, 'HelloStackoverflow') =>",
        checkString(arr, "HelloStackoverflow")
    );
    console.log(
        "checkString(arr, 'itIsAwfullyColdDayToday') =>",
        checkString(arr, "itIsAwfullyColdDayToday")
    );
    .as-console {background-color:black !important; color:lime;}
    .as-console-wrapper {max-height:100% !important; top:0;}

    【讨论】:

    • 之前没想过使用lookahead assertion。绝对是一个很好的方法。谢啦。 +1
    【解决方案2】:

    在进行比较之前,您必须将拆分字符串转换为小写。

    此外,当字符串的第一个字母为大写时,您必须删除由replace 插入的列表开头的空字符串。

    您可以使用includes 代替indexOf

    var arr = ["hello", "have", "a", "good", "day", "stackoverflow"];
    
    function checkString(wordArray, str) {
        return str.replace(/([A-Z])/g, ' $1')
          .split(" ") // split on spaces
          .map(s => s.toLowerCase())
          .filter(s => s)
          .every(e => wordArray.includes(e));
    }
    
    console.log("should return true -> " + checkString(arr, "HelloStackoverflow"));
    console.log("should return false -> " + checkString(arr, "itIsAwfullyColdDayToday"));

    【讨论】:

    • 我指定了 toLowerCase() 但之前复制了错误的 sn-p。在字符串以大写字母开头的情况下,我忽略了空拆分字符串。谢啦。 +1
    • .filter(s => s) 的目的是什么?
    • @Taki ["","hello"].filter(f => f) 将产生["hello"],这只是摆脱带有空白字符串的元素的简单方法。
    • @Taki 我认为过滤器会删除当Hello<space_here>Hello 替换然后由space 拆分生成数组["", "Hello"] 时生成的空字符串。在他的帖子的上一版本中对此有评论。
    • 这是一个很好的答案,但 lookahead assertion 方法更简洁 imo。 lookahead assertion 不是处理生成的空字符串,而是首先确保不会生成空字符串。
    【解决方案3】:

    你很接近,但有两个问题:

    • 其中一个在您的 str.replace 上,当您在字符串的开头有一个大写字母时,它会返回类似 ["", "Hello", "Stackoverflow"] 的内容。

    • 第二个在你的比较中 wordArray.indexOf() 它是区分大小写的,所以你需要添加 toLowerCase() 所以它最终是这样的:wordArray.indexOf(e.toLowerCase())

    var arr = ["hello", "have", "a", "good", "day", "stackoverflow"];
    
    function checkString(wordArray, str) {
      var x = str.replace(/([A-Z])/g, ' $1').split(" "); // split the camelCase words
      //filter spaces
      var filtered = x.filter(s => s != '');
      return filtered.every(e => {
        return wordArray.indexOf(e.toLowerCase()) >= 0;
      });
    }
    
    console.log("should return true ->" + checkString(arr, "HelloStackoverflow"));
    console.log("should return false ->" + checkString(arr, "itIsAwfullyColdDayToday"));

    【讨论】:

    • 我指定了 toLowerCase() 但之前复制了错误的 sn-p。在字符串以大写字母开头的情况下,我忽略了空拆分字符串。谢啦。 +1
    【解决方案4】:

    一些问题:首先,所有arr 值都以小写字母开头,但是您的驼峰式测试(当然)包含大写字母。所以我换了

    wordArray.indexOf(e)
    

    wordArray.indexOf(e.toLowerCase())
    

    其次,由于您的第一个测试用例以大写字母开头,因此您的正则表达式会添加一个空格,然后将split 变成它自己的“单词”。为了解决这个问题,我刚刚将!e || 添加到every 条件中,因此对于前导大写字母生成的空字符串,它将始终返回true。

    var arr = ["hello", "have", "a", "good", "day", "stackoverflow"];
    
    function checkString(wordArray, str) {
        var x = str.replace(/([A-Z])/g, ' $1').split(" "); // split the camelCase words
        return x.every(function (e) { return !e || wordArray.indexOf(e.toLowerCase()) >= 0; });
    }
    
    console.log("should return true ->" + checkString(arr, "HelloStackoverflow"));
    console.log("should return false ->" + checkString(arr, "itIsAwfullyColdDayToday"));

    【讨论】:

    • 我指定了 toLowerCase() 但之前复制了错误的 sn-p 但这是一种处理初始空字符串的好方法。 +1
    【解决方案5】:

    这是一个非常简单的版本。

    const checkString = arr => str => str
      .split(/(?=[^a-z])/)
      .every(s => arr.includes(s.toLowerCase()))
    
    const arr = ["hello", "have", "a", "good", "day", "stackoverflow"]
    
    console.log(checkString(arr)('whenTheDayAndNightCollides'))
    console.log(checkString(arr)('HaveAGoodDay'))
    console.log(checkString(arr)('itIsAwfullyColdDayToday'))
    console.log(checkString(arr)('HelloStackoverflow'))

    当然你也可以命名中间函数:

    const correct = checkString(arr)
    correct('HaveAStackoverflowDay') //=> true
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-25
      • 2018-12-15
      • 2019-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多