如何拆分camelCase字符串并检查每个拆分词是不是是数组的一部分?

Posted

技术标签:

【中文标题】如何拆分camelCase字符串并检查每个拆分词是不是是数组的一部分?【英文标题】: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", "***"];
var str1 = "whenTheDayAndNightCollides";
var str2 = "HaveAGoodDay";
var str3 = "itIsAwfullyColdDayToday";
var str4 = "Hello***";

如何将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

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

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

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

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, "Hello***"));
console.log("should return false ->" + checkString(arr, "itIsAwfullyColdDayToday"));

我做错了什么?

【问题讨论】:

【参考方案1】:

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

const arr = ["hello", "have", "a", "good", "day", "***"];

function checkString(wordArray, str)

    return str.split(/(?=[A-Z])/g).every(
        e => wordArray.includes(e.toLowerCase())
    );


console.log(
    "checkString(arr, 'Hello***') =>",
    checkString(arr, "Hello***")
);
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", "***"];

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, "Hello***"));
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", "***"] 的内容。

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

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

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, "Hello***"));
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", "***"];

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, "Hello***"));
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", "***"]

console.log(checkString(arr)('whenTheDayAndNightCollides'))
console.log(checkString(arr)('HaveAGoodDay'))
console.log(checkString(arr)('itIsAwfullyColdDayToday'))
console.log(checkString(arr)('Hello***'))

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

const correct = checkString(arr)
correct('HaveA***Day') //=> true

【讨论】:

以上是关于如何拆分camelCase字符串并检查每个拆分词是不是是数组的一部分?的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中进行CamelCase拆分

使用php preg_match(正则表达式)将camelCase单词拆分为单词

如何在不破坏单词的情况下将字符串拆分为行?

如何拆分字符串数组,然后将该拆分数组的每个第一个索引与字符进行比较?

如何将字符串字典转换为字典并拆分为单独的列

使用拆分字符串自定义共享按钮中的意图或如何拆分字符串并替换奇数逗号