Гуманизируйте строку в JavaScript

Как я гуманизирую строку? На основании следующих критериев:

  • Удаляет первые подчеркивания, если они есть.
  • Заменяет подчеркивание пробелами, если они есть.
  • С заглавной буквы первое слово.

Например:

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

6 ответов

Лучше всего использовать некоторые регулярные выражения:

^[\s_]+|[\s_]+$ Ловит 1 или более символов пробела или подчеркивания либо в самом начале (^) или в самом конце ($) строки. Обратите внимание, что это также ловит символы новой строки. Замените их пустой строкой.

[_\s]+ Снова ловит 1 или более символов пробела или подчеркивания, так как те, что в начале / конце строки пропали, замените 1 пробелом.

^[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>

Это охватывает все ваши дела:

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' ]
*/

Лодаш имеет _.startCase что хорошо для гуманизации объектных ключей. Преобразование подчеркивает штрихи и верблюжий корпус в пространствах.

В вашем случае вы хотите извлечь выгоду, но поддерживать верблюжий случай. Этот вопрос был задан некоторое время назад. В настоящее время я предпочитаю создавать класс, который обрабатывает мутации. Его проще тестировать и поддерживать. Поэтому, если в будущем вам понадобится поддерживать преобразования типа "1Item" в "First item", вы можете написать одну функцию с единственной ответственностью.

Приведенное ниже является более дорогим в вычислительном отношении, но более легким в обслуживании. Есть одна понятная функция 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;
};

Хотя я думаю, что эксперт по регулярным выражениям мог бы сделать что-то подобное в одной строке, лично я бы сделал что-то подобное.

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?"
   ]
 */

Я предпочитаю использовать string.js, который включает в себя различные методы для работы со строками, в том числе humanize(),

Другой вариант:

      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(); });
}
Другие вопросы по тегам