在Javascript中将字符串转换为帕斯卡命名法(也称为UpperCamelCase)

46

我想知道如何在JavaScript中将字符串转换为帕斯卡命名法的字符串(最可能是使用正则表达式)。

转换示例:

  • double-barrel = Double-Barrel
  • DOUBLE-BARREL = Double-Barrel
  • DoUbLE-BaRRel = Double-Barrel
  • double barrel = Double Barrel

有关帕斯卡命名法的更多信息,请查看此链接

7个回答

66
s = s.replace(/(\w)(\w*)/g,
        function(g0,g1,g2){return g1.toUpperCase() + g2.toLowerCase();});
正则表达式找到单词(使用 \w 定义 - 包括字母数字和下划线),并将它们分为两组 - 第一个字母和剩余部分。然后使用函数作为回调来设置正确的大小写。
示例:http://jsbin.com/uvase 或者,这个方法也可以工作 - 它使用更少的正则表达式和更多的字符串操作:
s = s.replace(/\w+/g,
        function(w){return w[0].toUpperCase() + w.slice(1).toLowerCase();});

需要说明:这并不是帕斯卡命名法,因为你有单词间的障碍(helloworldhello-world)。如果没有它们,问题几乎无法解决,即使有字典也不行。这更常被称作标题案例,但它不能处理"FBI", "the" 或者 "McDonalds"这样的词语。


2
完全正确,虽然我认为标题大小写不同于帕斯卡命名法(Upper Camel Case)标题大小写 = 双管 帕斯卡命名法 = 双管 - Blowsie
标题大小写可能会产生误导。它有一个独特的含义,不符合正常的英语规则。Titlecase是Unicode的大小写属性,主要用于只有第一个字母应大写的情况。它对某些双字母组合的应用方式与其他字符不同,例如DZ vs Dz vs dz。相比之下,英语标题的适当大写方式完全不同,忽略短介词,除非是第一个或最后一个单词等。 - tchrist
3
这不应该被接受作为答案。尝试将字符串 fooBar 转换为 FooBar,它将失败。 - Renan Coelho
@RenanCoelho - 这太严厉了。有许多种“转换为帕斯卡命名法”的方法。在这个问题中,OP想忽略单词的原始大小写 - DoUbLE -> Double。如果您的情况不同,我相信您可以找到一个更合适的问题。 - Kobi
它也无法处理带有变音符号的字符。 - Vlad C
这里是一个一行的Typescript版本的答案:https://stackoverflow.com/questions/4068573/77132567#answer-77132567 - undefined

37

这是我的建议:

function toPascalCase(string) {
  return `${string}`
    .toLowerCase()
    .replace(new RegExp(/[-_]+/, 'g'), ' ')
    .replace(new RegExp(/[^\w\s]/, 'g'), '')
    .replace(
      new RegExp(/\s+(.)(\w*)/, 'g'),
      ($1, $2, $3) => `${$2.toUpperCase() + $3}`
    )
    .replace(new RegExp(/\w/), s => s.toUpperCase());
}
或者
String.prototype.toPascalCase = function() {
  return this
    .toLowerCase()
    .replace(new RegExp(/[-_]+/, 'g'), ' ')
    .replace(new RegExp(/[^\w\s]/, 'g'), '')
    .replace(
      new RegExp(/\s+(.)(\w*)/, 'g'),
      ($1, $2, $3) => `${$2.toUpperCase() + $3}`
    )
    .replace(new RegExp(/\w/), s => s.toUpperCase());
};

测试用例:

describe('String to pascal case', function() {
  it('should return a pascal cased string', function() {
    chai.assert.equal(toPascalCase('foo bar'), 'FooBar');
    chai.assert.equal(toPascalCase('Foo Bar'), 'FooBar');
    chai.assert.equal(toPascalCase('fooBar'), 'FooBar');
    chai.assert.equal(toPascalCase('FooBar'), 'FooBar');
    chai.assert.equal(toPascalCase('--foo-bar--'), 'FooBar');
    chai.assert.equal(toPascalCase('__FOO_BAR__'), 'FooBar');
    chai.assert.equal(toPascalCase('!--foo-¿?-bar--121-**%'), 'FooBar121');
    chai.assert.equal(toPascalCase('Here i am'), 'HereIAm');
    chai.assert.equal(toPascalCase('FOO BAR'), 'FooBar');
  });
});

1
谢谢建议!刚刚更新了函数。 - kalicki2k
1
砰!互联网变得更好了 ;) @kalicki2k - roscioli
1
非常感谢,对我所有需要的情况都非常有效 ^^ - Mitsuha Kitsune
1
似乎存在所有大写字母的问题(例如“FOO BAR”)。第一个单词仍然完全大写。如果将${string}更改为_${string},则对于第一个单词有效(这是我能找到的最不具侵入性的解决方法)。 - Andrew Samuelson
3
不适用于“FooBar”和“fooBar”。 - E. Faslo

23

如果破折号、空格和其他符号被用作字符串分隔符,可以使用lodash

例如:

_.upperFirst(_.camelCase('double-barrel')); // => DoubleBarrel

这只转换了第一个字母。它输出的是Double-barrel而不是DoubleBarrel - nelson6e65
你使用过 _.camelCase 吗?请再次检查示例。 - user2809176
1
伟大的解决方案,也适用于使用.分隔符的情况(即double.barrel => DoubleBarrel)。 - quicklikerabbit

1
function toPascalCase (str) {
  if (/^[a-z\d]+$/i.test(str)) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }
  return str.replace(
    /([a-z\d])([a-z\d]*)/gi,
    (g0, g1, g2) => g1.toUpperCase() + g2.toLowerCase()
  ).replace(/[^a-z\d]/gi, '');
}

我从Kobi's answer开始,使用了kalicki2k's answer中的Chai测试来进行测试。

通过将a-z更改为\p{L}并添加u标志, 可以添加简单的多语言支持:

function toPascalCase (str) {
  if (/^[\p{L}\d]+$/iu.test(str)) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }
  return str.replace(
    /([\p{L}\d])([\p{L}\d]*)/giu,
    (g0, g1, g2) => g1.toUpperCase() + g2.toLowerCase()
  ).replace(/[^\p{L}\d]/giu, '');
}

只有在启用 Unicode 版本时才通过的两个额外测试:

chai.assert.equal(toPascalCase('ça.roule'), 'ÇaRoule');
chai.assert.equal(toPascalCase('добрий-день'), 'ДобрийДень');

顺便提一下,非 Unicode 版本大约比 Unicode 版本和 kalicki2k 的版本快两倍。但这并不重要,它们都足够快。

如果您需要缓存:

const pascalCache = {};
function toPascalCase (str) {
    pascalCache[str] =
        pascalCache[str] ||
        (
            /^[a-z\d]+$/i.test(str) &&
            str.charAt(0).toUpperCase() + str.slice(1)
        ) ||
        str.replace(
            /([a-z\d])([a-z\d]*)/gi,
            (g0, g1, g2) => g1.toUpperCase() + g2.toLowerCase()
        ).replace(/[^a-z\d]/gi, '');

    return pascalCache[str];
}

缓存加多语言:

const pascalCache = {};
function toPascalCase (str) {
    pascalCache[str] =
        pascalCache[str] ||
        (
            /^[\p{L}\d]+$/iu.test(str) &&
            str.charAt(0).toUpperCase() + str.slice(1)
        ) ||
        str.replace(
            /([\p{L}\d])([\p{L}\d]*)/giu,
            (g0, g1, g2) => g1.toUpperCase() + g2.toLowerCase()
        ).replace(/[^\p{L}\d]/giu, '');

    return pascalCache[str];
}

这些版本在基准测试中似乎快了很多(8倍),但当然这并不是真实世界使用的好代表。


如果有人在寻找如何将首字母缩写词转换为帕斯卡命名法,你可以将以下代码行添加到函数中: str = str.replace(/((?<=[A-Z])[A-Z]+)/g, (_, g1) => g1.toLowerCase()), chai测试: chai.assert.equal(toPascalCase('BAR'), 'Bar'); chai.assert.equal(toPascalCase('fooBARfoo'), 'FooBarfoo'); - chesiren
toPascalCase('some-case_lol_whatIsThis') 'SomeCaseLolWhatisthis' 看起来有点不对...因为IsThis已经是帕斯卡命名法了! - undefined

0
更简单的版本,带有去除空格选项:
const toPascalCase = (text, trimSpace=false) => text.split(' ').map((t) => t[0].toUpperCase() + t.slice(1).toLowerCase()).join(trimSpace?'':' ')


测试:

const toPascalCase = (text, trimSpace=false) => text.split(' ').map((t) => t[0].toUpperCase() + t.slice(1).toLowerCase()).join(trimSpace?'':' ')

console.log(toPascalCase('hello world')); // Output: "Hello World"
console.log(toPascalCase('foo bar baz')); // Output: "Foo Bar Baz"
console.log(toPascalCase('this is a sample text')); // Output: "This Is A Sample Text"


0
一个使用Typescript编写的一行代码版本this answer,还可以处理字符串为null/undefined的情况。
const toPascalCase = (s: string | null | undefined) =>
  s ? s.replace(/(\w)(\w*)/g, (_, p, q) => p.toUpperCase() + q.toLowerCase()) : s;

-2
const toPascalCase = (sentence) => sentence
   .toLowerCase()
   .replace(new RegExp(/[-_]+/, 'g'), ' ')
   .replace(new RegExp(/[^\w\s]/, 'g'), '')
   .trim()
   .split(' ')
   .map(word => word[0]
   .toUpperCase()
   .concat(word.slice(1)))
   .join('');

toPascalCase(words);

does not remove "_" - Capaj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接