在JavaScript中将一个字符串人性化

14

如何将字符串“人性化”? 基于以下标准:

  • 删除前导下划线(如果有)。
  • 将下划线替换为空格(如果有)。
  • 将第一个单词大写。

例如:

this is a test -> This is a test
foo Bar Baz    -> Foo bar baz
foo_bar        -> Foo bar
foo_bar_baz    -> Foo bar baz
foo-bar        -> Foo-bar
fooBarBaz      -> FooBarBaz

我猜如果是驼峰命名法,应该保持不变?带有破折号的单词也遵循相同的原则。但第一个字符应始终大写。我进行了编辑。 - Christian Fazzini
5个回答

14

最好使用一些正则表达式:

^[\s_]+|[\s_]+$ 匹配字符串开头或结尾的一个或多个空白字符或下划线 (^$)。请注意,这也可以捕获换行符。用空字符串替换它们。

[_\s]+ 再次匹配一个或多个空格字符或下划线,因为在字符串的开头/结尾处的已经被删除了,将其替换为一个空格。

^[a-z] 在字符串开头匹配一个小写字母。用匹配项的大写版本替换它(需要一个回调函数来实现)。

组合起来:

function humanize(str) {
  return str
      .replace(/^[\s_]+|[\s_]+$/g, '')
      .replace(/[_\s]+/g, ' ')
      .replace(/^[a-z]/, function(m) { return m.toUpperCase(); });
}

document.getElementById('out').value = [
  '    this is a test',
  'foo Bar Baz',
  'foo_bar',
  'foo-bar',
  'fooBarBaz',
  '_fooBarBaz____',
  '_alpha',
  'hello_ _world,   how    are________you?  '
].map(humanize).join('\n');
textarea { width:100%; }
<textarea id="out" rows="10"></textarea>


这越来越接近一行代码了... :) - istos
@istos 一行代码,呵呵,我很久以前就在我的个人简介中写明了正则表达式只是一种工具,而不是解决方案。可以编写一个正则表达式来捕获所有内容,然后在回调函数中检查匹配并决定需要什么处理(删除?替换为空格?大写?)。但这样的代码会更难阅读和维护。如果您的数据集非常大,以至于单个正则表达式替换调用的性能显着提高,那么您本来就不应该使用JavaScript在客户端处理这些数据 ;) - asontu
好观点,尤其是这一点:“单行代码不代表什么” :) - istos

8
这涵盖了你所有的情况:
var tests = [
  'this is a test',
  'foo Bar Baz',
  ...
]

var res = tests.map(function(test) {
  return test
    .replace(/_/g, ' ')
    .trim()
    .replace(/\b[A-Z][a-z]+\b/g, function(word) {
      return word.toLowerCase()
    })
    .replace(/^[a-z]/g, function(first) {
      return first.toUpperCase()
    })
})

console.log(res)
/*
[ 'This is a test',
  'Foo bar baz',
  'Foo bar',
  'Foo-bar',
  'FooBarBaz' ]
*/

1
可以使用replace(/_/g, ' ')来替换所有的下划线,而不是使用'foo_bar_baz'.replace(/_/, ' ')。这样做是有效的。 - Christian Fazzini

3

Lodash有_.startCase函数,用于将对象键转换为易读形式。可以将下划线、破折号和驼峰命名法转换为空格。

在您的情况下,您想要大写但保留驼峰命名法。这个问题以前被问过。我目前的首选是创建一个处理变异的类。这更容易测试和维护。因此,如果将来需要支持像“1Item”转换为“第一项”之类的转换,则可以编写一个具有单一职责的函数。

以下代码计算开销更大,但更易于维护。它有一个清晰的toHumanString函数,可以轻松理解和修改。

export class HumanizableString extends String {
  capitalizeFirstLetter() => {
    const transformed = this.charAt(0).toUpperCase() + this.slice(1);
    return new HumanizableString(transformed);
  };

  lowerCaseExceptFirst() => {
    const transformed = this.charAt(0) + this.slice(1).toLowerCase();
    return new HumanizableString(transformed);
  };

  camelCaseToSpaces() => {
    const camelMatch = /([A-Z])/g;
    return new HumanizableString(this.replace(camelMatch, " $1"));
  };

  underscoresToSpaces() => {
    const camelMatch = /_/g;
    return new HumanizableString(this.replace(camelMatch, " "));
  };

  toHumanString() => {
    return this.camelCaseToSpaces()
      .underscoresToSpaces()
      .capitalizeFirstLetter()
      .lowerCaseExceptFirst()
      .toString();
  };
}

至少,您应该为您的正则表达式命名,以使它们更易读。

export const humanise = (value) => {
  const camelMatch = /([A-Z])/g;
  const underscoreMatch = /_/g;

  const camelCaseToSpaces = value.replace(camelMatch, " $1");
  const underscoresToSpaces = camelCaseToSpaces.replace(underscoreMatch, " ");
  const caseCorrected =
    underscoresToSpaces.charAt(0).toUpperCase() +
    underscoresToSpaces.slice(1).toLowerCase();

  return caseCorrected;
};

希望有一个简单的实用程序专门处理这个。 - Vadorequest

2

虽然我认为正则表达式专家可以在一行代码中完成这样的操作,但个人而言,我会像这样做。

function humanize(str) {
  return str.trim().split(/\s+/).map(function(str) {
    return str.replace(/_/g, ' ').replace(/\s+/, ' ').trim();
  }).join(' ').toLowerCase().replace(/^./, function(m) {
    return m.toUpperCase();
  });
}

测试:

[
  '    this is a test',
  'foo Bar Baz',
  'foo_bar',
  'foo-bar',
  'fooBarBaz',
  '_fooBarBaz____',
  '_alpha',
  'hello_ _world,   how    are________you?  '
].map(humanize);

/* Result:
   [
     "This is a test", 
     "Foo bar baz", 
     "Foo bar", 
     "Foo-bar", 
     "Foobarbaz", 
     "Foobarbaz", 
     "Alpha", 
     "Hello world, how are you?"
   ]
 */

1
另一个选项:
const humanize = (s) => {
  if (typeof s !== 'string') return s
  return s
      .replace(/^[\s_]+|[\s_]+$/g, '')
      .replace(/[_\s]+/g, ' ')
      .replace(/\-/g, ' ')
      .replace(/^[a-z]/, function(m) { return m.toUpperCase(); });
}

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