在 JavaScript 中将驼峰案转为烤肉串

Sta*_*ack 9 javascript ecmascript-6

我有一个 kebabize 函数,可以将驼峰式转换为烤肉串。我正在分享我的代码。可以更优化吗?我知道这个问题可以使用正则表达式来解决。但是,我想在不使用正则表达式的情况下做到这一点。

const kebabize = str => {

    let subs = []
    let char = ''
    let j = 0

    for( let i = 0; i < str.length; i++ ) {

        char = str[i]

        if(str[i] === char.toUpperCase()) {
            subs.push(str.slice(j, i))
            j = i
        }

        if(i == str.length - 1) {
            subs.push(str.slice(j, str.length))
        }
    }

    return subs.map(el => (el.charAt(0).toLowerCase() + el.substr(1, el.length))).join('-')
}

kebabize('myNameIsStack')
Run Code Online (Sandbox Code Playgroud)

ABa*_*bin 50

我有一个类似于 Marc 的单行代码,但具有更简单的正则表达式,并且根据我的基准测试(Chrome 89),速度提高了约 20%。

const kebabize = (str) => str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? "-" : "") + $.toLowerCase())

const words = ['StackOverflow', 'camelCase', 'alllowercase', 'ALLCAPITALLETTERS', 'CustomXMLParser', 'APIFinder', 'JSONResponseData', 'Person20Address', 'UserAPI20Endpoint'];

console.log(words.map(kebabize));
Run Code Online (Sandbox Code Playgroud)

[A-Z]+(?![a-z])匹配任何连续的大写字母,不包括任何大写字母后跟小写字母(表示下一个单词)。然后添加|[A-Z]包括任何单个大写字母。它必须在连续大写表达式之后,否则表达式将单独匹配所有大写字母,并且永远不会匹配连续的。

String.prototype.replace可以带替换功能。在这里,当匹配偏移量为真(不为零 - 不是字符串的第一个字符)时,在添加连字符前缀后,它返回每个单词的小写匹配大写字母。

我怀疑 Marc 的解决方案比我的解决方案性能较差,因为通过使用替换来插入连字符并随后将整个字符串小写,它必须多次迭代字符串,并且其表达式还具有更复杂的前向/后向结构。

基准


Ami*_*adi 17

正则表达式更快!

与您可能想象的不同,RegEx 的执行方式实际上要快得多!请参阅基准

下面的函数支持将camelCase和转换PascalCasekebab-case

function toKebabCase(str) {
    return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
}
Run Code Online (Sandbox Code Playgroud)

  • 对于完全大写的单词,此操作会失败。`JSONResponseData` 将返回 `jsonresponse-data` 而不是 `json-response-data`。我认为这可能是一种风格选择,但我认为这并不是大多数人所期望的,如果他们没有意识到,就会引起问题。 (5认同)
  • @NNL993 没有“正确”的标准。有些人使用“camelCase”大写首字母缩略词 - 有时达到一定长度,或者选择性地或始终大写。这里的其他解决方案可以处理这些情况,而不会显着增加开销。 (2认同)

Nic*_*ies 15

const kebabize = str => {
   return str.split('').map((letter, idx) => {
     return letter.toUpperCase() === letter
      ? `${idx !== 0 ? '-' : ''}${letter.toLowerCase()}`
      : letter;
   }).join('');
}

console.log(kebabize('myNameIsStack'));
console.log(kebabize('MyNameIsStack'));
Run Code Online (Sandbox Code Playgroud)

您可以检查每个字母是否为大写并替换它。

  • `str.split("")` 给出了由多个部分组成的 unicode 符号的意外结果。使用“[...str]”或“Array.from(str)”。 (3认同)
  • 仅当输入字符串为驼峰式命名而不是大驼峰式命名时,此方法才有效 (2认同)
  • @VinayMahamuni UpperCamelCase 是 PascalCase 仅供参考,它不一样。 (2认同)

Mar*_*ing 11

这是我的解决方案:

适用于驼峰命名法和帕斯卡命名法:

let words = ['StackOverflow', 'camelCase', 'alllowercase', 'ALLCAPITALLETTERS', 'CustomXMLParser', 'APIFinder', 'JSONResponseData', 'Person20Address', 'UserAPI20Endpoint'];

let result = words.map(w => w.replace(/((?<=[a-z\d])[A-Z]|(?<=[A-Z\d])[A-Z](?=[a-z]))/g, '-$1').toLowerCase());

console.log(result);

/*

Returns:
[
  "stack-overflow",
  "camel-case",
  "alllowercase",
  "allcapitalletters",
  "custom-xml-parser",
  "api-finder",
  "json-response-data",
  "person20-address",
  "user-api20-endpoint"
]

*/
Run Code Online (Sandbox Code Playgroud)

解释:

  1. 匹配以下任意正则表达式:
  • 查找任何大写字母,其前面紧跟着一个小写字母或数字,或者
  • 查找前面紧跟一个大写字母的任何大写字母或后面紧跟一个小写字母的数字
  1. 将捕获的位置替换为破折号(“-”),后跟捕获的大写字母
  2. 最后,将整个字符串转换为小写。