将蛇形命名字符串转换为标题格式

6

我有一个蛇形变量 big_animal
我想把它转换成 Big Animal

我的方法是 str => str.replace(/([-_]\w)/g, g => g[1].toUpperCase());

但我一直得到的是 bigAnimal,而我想保留空格并将第一个字母大写。

4个回答

15

另一个简单的正则表达式版本:

const titleCase = (s) =>
  s.replace(/^_*(.)|_+(.)/g, (s, c, d) => c ? c.toUpperCase() : ' ' + d.toUpperCase())

console .log (titleCase ('big_animal'))
console .log (titleCase ('_big_animal___with_more_Nodes'))

这个版本可以处理连续的下划线。它有单独匹配第一个字符(或以下划线开头的字符)和那些跟在一定数量下划线后面的字符的模式,对于后者添加了一个空格。

更新

经过思考,我认为最好用两个正则表达式进行替换:

const titleCase = (s) =>
  s.replace (/^[-_]*(.)/, (_, c) => c.toUpperCase())       // Initial char (after -/_)
   .replace (/[-_]+(.)/g, (_, c) => ' ' + c.toUpperCase()) // First char after each -/_

console .log (titleCase ('big_animal'))
console .log (titleCase ('_big_animal___with-more--Nodes'))

这个变量还添加了对短横线命名法(kebab case)的处理。


请注意,这仅处理下划线。从问题的尝试来看,我认为正则表达式中的下划线应该用“[-_]”替换。这应该是一个简单的修复。 - Scott Sauyet
在初始的 replace() 前添加 toLowerCase() 可能也是可取的,以使其真正成为标题大小写。否则,您可能最终会得到 big_aNIMAL,结果将是 Big ANIMAL - Zei
1
@Zei:另一方面,'my_HTML_renderer'将变成'My Html Renderer',这也可能会带来问题。我认为,如果这是所期望的内容,最好调用titleCase(myString.toLowerCase())。但因人而异。 - Scott Sauyet
好想法。这甚至可能与我的用例相关。我需要编辑自己的函数。我可以使用正则表达式来忽略一个单词,当它全部大写时,然后仅将小写应用于不是全部大写的单词。虽然可能不会像你的一行代码那样顺畅。 - Zei
1
对于第一个基于正则表达式的解决方案,我会使用以下代码以避免任何尾随下划线字符: const titleCase = (s) => s.replace(/^_*(.)|_+(.?)/g, (s, c, d) => c ? c.toUpperCase() : d ? ' ' + d.toUpperCase() : ''); - Tuhin Paul

8

首先按下划线拆分字符串,然后将第一个字母大写。

let str = "big_animal";

let ret = str
  .split("_")
  .filter(x => x.length > 0)
  .map((x) => (x.charAt(0).toUpperCase() + x.slice(1)))
  .join(" ");
console.log(ret);


请注意,如果第一个字符是下划线或有多个连续的下划线,则此操作将添加前导空格。 - Scott Sauyet
@Scott现在可以了吗? - mr hr
在我看来是这样的。但它增加了足够的复杂性,我可能更喜欢一个正则表达式版本。不过,这仍然是一个展示小步骤简单性的好演示! - Scott Sauyet

3

如果你想坚持使用正则表达式方法。

let str = "big_animal_and_more"
let output = str.replace(/(^\w)/g, g => g[0].toUpperCase()).replace(/([-_]\w)/g, g => " " + g[1].toUpperCase()).trim();
console.log(output);


请注意,如果第一个字符是下划线或有多个连续的下划线,则此操作将添加前导空格。 - Scott Sauyet
我之前不知道在“蛇形命名法”中前导下划线是一种惯例。但如果这是个问题,只需在输出上使用.trim()即可解决。 - Rob S.
请注意,此答案还包括从短横线命名法转换,这更接近于问题中定义的正则表达式模式。 - Rob S.
是的,我在发布答案后注意到了相同的烤肉串命名法替代方案,只是添加了一条评论而没有更改代码。 - Scott Sauyet
我更新了我的答案,包括.trim(),感谢您的观察。 - Rob S.

0
这是基于上述解决方案的TypeScript等效版本。
/**
 * String Converter to convert snake_case to Title Case
 * Eg.
 * - quick_brown_fox -> Quick Brown Fox
 * - quick_brown____fox -> Quick Brown Fox
 * - quick_brown_fox----jumps_over -> Quick Brown Fox Jumps Over
 *
 */

const convertSnakeToTitleCase = (s: string): string =>
  s
    .replace(/^[-_]*(.)/, (_, c: string) => c.toUpperCase())
    .replace(/[-_]+(.)/g, (_, c: string) => ' ' + c.toUpperCase());

这里是基于JEST的测试。
import { convertSnakeToTitleCase } from './helpers';

describe('convertSnakeToTitleCase helper function unit tests', () => {
  it('returns correct output for regular snake case string', () => {
    expect(convertSnakeToTitleCase('quick_brown_fox')).toBe('Quick Brown Fox');
  });

  it('returns correct output for snake case strings with consecutive underscores', () => {
    expect(convertSnakeToTitleCase('quick_brown_____fox')).toBe(
      'Quick Brown Fox'
    );
  });

  it('returns correct output for snake case strings with hyphen separated strings', () => {
    expect(convertSnakeToTitleCase('quick_brown_fox-----jumps_over')).toBe(
      'Quick Brown Fox Jumps Over'
    );
  });
});

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