Konwertuj ciąg znaków na wielkość liter za pomocą JavaScript

548

Czy istnieje prosty sposób konwersji ciągu na wielkość liter? Na przykładjohn smithJohn Smith . Staje się . Nie szukam czegoś skomplikowanego jak rozwiązanie Johna Resiga , tylko (mam nadzieję) jakiś jedno- lub dwuwarstwowy .

MDCore
źródło
Istnieją różne metody, czy mamy jakieś statystyki wydajności?
theAnubhav
Sprawdź tę krótką odpowiedź stackoverflow.com/a/57689168/10373693 Mam nadzieję, że to będzie odpowiedź, której szukasz.
Abhishek Kumar

Odpowiedzi:

739

Spróbuj tego:

    function toTitleCase(str) {
        return str.replace(
            /\w\S*/g,
            function(txt) {
                return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
            }
        );
    }
<form>
Input:
<br /><textarea name="input" onchange="form.output.value=toTitleCase(this.value)"  onkeyup="form.output.value=toTitleCase(this.value)"></textarea>
<br />Output:
<br /><textarea name="output" readonly onclick="select(this)"></textarea>
</form>

Greg Dean
źródło
14
Czy ktoś mógłby wyjaśnić, dlaczego \w\S*jest używany zamiast \w+lub \w*na przykład? Nie wiem, dlaczego chcesz wstawić tylko spacje i dlatego zmienić Jim-Bob na Jim-bob .
martinczerwi
5
@martinCzerwi \w\S*również spowodował Jim-bobproblem z naszej strony. Korzystanie \w*rozwiązało to.
Bouke
14
/([^\W_]+[^\s-]*) */grozwiązuje Jim-Bobproblem, tj .:jim-bob --> Jim-Bob
recursion.ninja
15
Jeśli takie jim-bob --> Jim-Bobjest twoje pragnienie, prawdopodobnie powinieneś to zrobić /\b\w+/g. Przykład:str.replace(/\b\w+/g,function(s){return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase();});
vol7ron
3
\w\S*jest używane zamiast \w+lub w \w*taki sposób, że słowa takie Don'tnie są modyfikowane Don'T, ale jak zauważyli inni, \w\S*powodują problemy ze słowami dzielonymi.
doubleDown
198

Nieco bardziej elegancki sposób, dostosowujący funkcję Grega Deana:

String.prototype.toProperCase = function () {
    return this.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
};

Nazwij to tak:

"pascal".toProperCase();
Tuan
źródło
3
Pamiętaj, jeśli masz użytkownika z myślnikiem w nazwie i wpisać Jo-Ann Smithten kod będzie przekonwertować je na Jo-ann Smith(uwaga na małe litery aw Ann).
dbau,
18
@daniellmb Dlaczego nie miałby zmieniać prototypu String? Myślę, że to dobre rozwiązanie. Pomyśl o rubinowych klasach otwartych, dodawanie funkcji do istniejących klas jest całkowicie poprawne i jest powszechnie akceptowane.
marco-fiset
97
@ marco-fiset Ponieważ nie gra dobrze z innymi! Złe rzeczy zdarzają się, gdy masz 2 biblioteki, które próbują modyfikować natywne obiekty JavaScript za pomocą niezgodnych zmian. Wyobraź sobie, że jeśli jQuery i Mapy Google postępują zgodnie z tym wzorcem projektowym, nie możesz mieć obu na tej samej stronie.
daniellmb,
5
@daniellmb Doskonały punkt. Prefiks nazwy metody powinien pomóc tego uniknąć, ponieważ spowoduje to, że metody nie będzie można wyliczyć.
mikemaccana
60
Wydaje mi się, że wyrażenie „nie modyfikuj natywnych obiektów JavaScript” jest takie samo jak „nigdy nie używaj goto” lub „eval is evil”. Jest wiele przypadków, w których jest w porządku. Jeśli masz pełną kontrolę nad swoim projektem i oczywiście nie planujesz wydać go jako biblioteki, nie widzę problemów z tą metodą.
FoxMulder900
175

Spróbuj zastosować styl CSS z transformacją tekstu do swoich kontrolek.

na przykład: (text-transform: capitalize);

Stosuj podejście JS tylko wtedy, gdy jest to absolutnie konieczne.

Talha Ashfaque
źródło
36
-1. Ten css działa, ale nie działa, jak większość ludzi się spodziewa, ponieważ jeśli tekst zaczyna się od wszystkich wielkich liter, nie ma efektu. webmasterworld.com/forum83/7506.htm
whitneyland
2
@Akshar: Reguła pisana małymi literami zostałaby zastąpiona regułą dotyczącą tytułów. Ponieważ css nie modyfikuje zawartości źródłowej, efektem jest usunięcie reguły pisanej małymi literami (pozostawianie zawartości źródłowej we wszystkich wielkich literach), a następnie zastosowanie miałaby zasada titlecase (nic nie robiąc).
dokkaebi
42
JS jest używany poza przeglądarkami.
mikemaccana
4
Pytanie brzmiało: „Czy istnieje prosty sposób konwersji ciągu na wielkość liter?” . Ta odpowiedź nie konwertuje ciągu. Jest to styl stosowany na sznurku.
kingPuppy
Jeśli chcesz, aby dane w bazie danych były czyste, aby można było z nich korzystać czysto podczas przesyłania do usług stron trzecich lub eksportowania do CSV, CSS nie jest tak naprawdę opcją. CSS jest przeznaczony do kosmetyków, i chociaż jest on rozrastany przez lata i można go używać do rozwiązywania tego rodzaju problemów, rozwiązanie pozostaje kosmetyczne i nie rozwiązuje podstawowego problemu.
Adam Reis
118

Oto moja wersja, IMO jest łatwa do zrozumienia i elegancka.

var str = "foo bar baz"

console.log(

str.split(' ')
   .map(w => w[0].toUpperCase() + w.substr(1).toLowerCase())
   .join(' ')

)
// returns "Foo Bar Baz"

a8m
źródło
3
Alternatywnie możesz mapować podciągi na małe litery:str.split(' ').map(i => i[0].toUpperCase() + i.substring(1).toLowerCase()).join(' ')
Dave Land
5
Nie zgadzam się z telefonowaniem .toLowerCase(). Nazwy takie jak „McDonald” lub akronimy takie jak „ASAP” powinny zachować swoje wielkie litery. Jeśli ktoś faktycznie przekazał ciąg taki jak „heLLO”, aplikacja nie powinna zakładać, że wielkie litery są niepoprawne.
Thomas Higginbotham
1
@ThomasHigginbotham Co powiesz na to? String.prototype.toTitleCase = function (blnForceLower) { var strReturn; (blnForceLower ? strReturn = this.toLowerCase() : strReturn = this); return strReturn .split(' ') .map(i => i[0].toUpperCase() + i.substr(1)) .join(' '); }
Sean Kendle,
Tak, preferowane byłoby zapewnienie opcji wymuszania małych liter.
Thomas Higginbotham
1
To się zepsuje, jeśli strjest to jedna postać.
Madbreaks,
103

Oto moja funkcja, która konwertuje na wielkość liter, ale zachowuje również zdefiniowane akronimy jako wielkie litery, a małe słowa jako małe:

String.prototype.toTitleCase = function() {
  var i, j, str, lowers, uppers;
  str = this.replace(/([^\W_]+[^\s-]*) */g, function(txt) {
    return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
  });

  // Certain minor words should be left lowercase unless 
  // they are the first or last words in the string
  lowers = ['A', 'An', 'The', 'And', 'But', 'Or', 'For', 'Nor', 'As', 'At', 
  'By', 'For', 'From', 'In', 'Into', 'Near', 'Of', 'On', 'Onto', 'To', 'With'];
  for (i = 0, j = lowers.length; i < j; i++)
    str = str.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'), 
      function(txt) {
        return txt.toLowerCase();
      });

  // Certain words such as initialisms or acronyms should be left uppercase
  uppers = ['Id', 'Tv'];
  for (i = 0, j = uppers.length; i < j; i++)
    str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), 
      uppers[i].toUpperCase());

  return str;
}

Na przykład:

"TO LOGIN TO THIS SITE and watch tv, please enter a valid id:".toTitleCase();
// Returns: "To Login to This Site and Watch TV, Please Enter a Valid ID:"
Geoffrey Booth
źródło
1
Podobało mi się twoje, mam również problemy z liczbami rzymskimi ... po prostu załatałem go za pomocą I, II, III, IV itd.
Marcelo
2
Naprawiony. Wyrażenie regularne w trzeciej linii zostało zmienione z /\w\S*/gna /([^\W_]+[^\s-]*) */gna komentarz powyżej @ awashburn, aby rozwiązać ten problem.
Geoffrey Booth
2
Czy istnieje przewaga /\b\w+/g, jaką można uzyskać, stosując wzorzec wyrażenia regularnego , który wydaje mi się szybszy do zrozumienia?
Michael - Where's Clay Shirky
2
Nie, że nie widzę, po prostu skorzystałem z sugestii innego komentatora, aby rozwiązać problem z łączonymi wyrazami; ale wyrażenie regularne wydaje się równie dobrze, a prostota jest zawsze lepsza. Dla potomnych i przyszłych gości tego postu właśnie zmieniłem regex w trzeciej linii z /([^\W_]+[^\s-]*) */gna /\b\w+/gna komentarz per @ Michael; prosimy o komentarz, jeśli znajdziesz przypadek, w którym konieczne jest zastosowanie bardziej skomplikowanego wyrażenia regularnego.
Geoffrey Booth
1
Zmieniłem regex trzeciej linii na /\b[\w-\']+/g, aby umożliwić łączenie wyrazów i apostrof w słowach.
Shamasis Bhattacharya
47

Wolę poniższe niż inne odpowiedzi. Dopasowuje tylko pierwszą literę każdego słowa i dodaje wielkie litery. Prostszy kod, łatwiejszy do odczytania i mniej bajtów. Zachowuje istniejące duże litery, aby zapobiec zniekształcaniu akronimów. Jednak zawsze możesz najpierw wywołać toLowerCase()swój ciąg.

function title(str) {
  return str.replace(/(^|\s)\S/g, function(t) { return t.toUpperCase() });
}

Możesz dodać to do swojego prototypu ciągu, co pozwoli ci 'my string'.toTitle()w następujący sposób:

String.prototype.toTitle = function() {
  return this.replace(/(^|\s)\S/g, function(t) { return t.toUpperCase() });
}

Przykład:

Tom Kay
źródło
3
Jest jeszcze ładniejszy jako lambdaconst titleCase = (str) => str.replace(/\b\S/g, t => t.toUpperCase());
0xcaff
Nie chciałem łamać IE, ale tak, jeśli aplikacja nie jest wrażliwa na starsze przeglądarki, może być krótsza.
Tom Kay
To tylko częściowe rozwiązanie - op poprosił o konwersję ciągu znaków na wielkość liter. Ta odpowiedź nie osiąga tego w przypadku danych wejściowych takich jak NoT qUiITe.
Madbreaks,
@Madbreaks Pytanie nie przewidywało, że dane wejściowe o mieszanej wielkości liter powinny być konwertowane. Zaktualizowałem jednak wzmiankę o odpowiedzi toLowerCase. Pamiętaj tylko, że złamałoby to akronimy. an HTML document: An HTML DocumentvsAn Html Document
Tom Kay
4
@Madbreaks Podczas gdy twój początkowy przykład został wymyślony, dobrze jest powiedzieć, że dane wyjściowe pozostałyby niezmienione, gdyby dane wejściowe zostały wielkie. Biorąc to pod uwagę, czuję, że odpowiedź jest taka, jaka jest (sugerowana edycja toLowerCase) jest bardziej elastyczna / użyteczna niż ta, która zakłada intencje programistów. Ta metoda odzwierciedla również funkcjonalność podobnych wbudowanych metod innych języków, takich jak PHP ( ucwords) i Golang ( strings.Title). .NET ( TextInfo.ToTitleCase) ciekawie działa w przypadku małych i wielkich liter, ale pozostawiłby również w pełni niezmienione wielkie litery.
Tom Kay,
20

Bez użycia wyrażenia regularnego wyłącznie w celach informacyjnych:

String.prototype.toProperCase = function() {
  var words = this.split(' ');
  var results = [];
  for (var i = 0; i < words.length; i++) {
    var letter = words[i].charAt(0).toUpperCase();
    results.push(letter + words[i].slice(1));
  }
  return results.join(' ');
};

console.log(
  'john smith'.toProperCase()
)

Mikrofon
źródło
Dzięki za rozwiązanie wolne od wyrażeń regularnych!
lucifer63,
20

var result =
  'this is very interesting'.replace(/\b[a-z]/g, (x) => x.toUpperCase())

console.log(result) // This Is Very Interesting

simo
źródło
Tylko pytanie, konstrukcja () służy do określania dopasowania w dowolnej sekwencji opcji: to znaczy, (a | b) odpowiada a lub b. Co robi konstrukcja (.)?
Michael Blackburn,
Dla każdego, kto miał to samo pytanie, definiuje zamienny „obiekt blob”, który jest używany w sekcji zamiennej. Obiekty BLOB są numerowane sekwencyjnie, pierwszy () jest wstawiany do 1 $, drugi do 2 $. Uznałem tę stronę za przydatną: javascript.info/tutorial/regular-expressions-methods
Michael Blackburn
Nie jestem w stanie sprawić, aby powyższe zadziałało, ale daleko mi do kreatora wyrażeń regularnych. Używam 'string'.replace(/^(.)(.*)/,function(s,p1,p2){return p1.toUpperCase()+p2;}) Znowu, to działa tylko na wielkie litery pierwszej litery, ale w przypadku, gdy tego potrzebujesz, moja konstrukcja działa.
Michael Blackburn,
1
Z jakiegoś powodu FF35 wydaje się dusić '$1'.toUpperCase(), wydaje się, że wielkie litery nie zostały wykonane przed przypisaniem wartości. 'string'.replace(/^(.){1}/,function(match) { return match.toUpperCase(); })
Obejście problemu
Cześć wszystkim, odpowiedź jest ustalona! Jestem pewien, że zadziałało, zanim go opublikowałem. W każdym razie dzięki za wkład!
simo
17

Możesz od razu toLowerCaseciąg, a następnie tylko toUpperCasepierwszą literę każdego słowa. Staje się bardzo prostym 1 linijką:

function titleCase(str) {
  return str.toLowerCase().replace(/\b(\w)/g, s => s.toUpperCase());
}

console.log(titleCase('iron man'));
console.log(titleCase('iNcrEdible hulK'));

KevBot
źródło
Podoba mi się to rozwiązanie; ładny i prosty. Wygląda na to, że odrobina CoffeeScript wślizgnęła się do twojej odpowiedzi ( s => s.toUpperCase()). Moim wariantem jest robienie tego, co zrobiłeś, ale rozszerzanie obiektu String (jakkolwiek kontrowersyjnego):Object.defineProperty(String.prototype, '_toProperCase', {value:function() {return this.toLowerCase().replace(/\b(\w)/g, function(t) {return t.toUpperCase()})}})
Waz
1
@Waz, dziękuję za pomysły! Chciałem tylko wyjaśnić, na czym =>polega natywna funkcja strzałki (ES6), link przeskakuje do nich w Dokumentach Mozillla, które również zapewniają tabelę wsparcia.
KevBot
16

Na wszelki wypadek, gdy martwisz się wypełniającymi słowami, zawsze możesz po prostu powiedzieć tej funkcji, czego nie należy pisać dużymi literami.

/**
 * @param String str The text to be converted to titleCase.
 * @param Array glue the words to leave in lowercase. 
 */
var titleCase = function(str, glue){
    glue = (glue) ? glue : ['of', 'for', 'and'];
    return str.replace(/(\w)(\w*)/g, function(_, i, r){
        var j = i.toUpperCase() + (r != null ? r : "");
        return (glue.indexOf(j.toLowerCase())<0)?j:j.toLowerCase();
    });
};

Mam nadzieję, że to ci pomoże.

edytować

Jeśli chcesz obsługiwać wiodące słowa kleju, możesz śledzić tę w / jeszcze jedną zmienną:

var titleCase = function(str, glue){
    glue = !!glue ? glue : ['of', 'for', 'and', 'a'];
    var first = true;
    return str.replace(/(\w)(\w*)/g, function(_, i, r) {
        var j = i.toUpperCase() + (r != null ? r : '').toLowerCase();
        var result = ((glue.indexOf(j.toLowerCase()) < 0) || first) ? j : j.toLowerCase();
        first = false;
        return result;
    });
};
fncomp
źródło
2
Możesz rozbić ciąg na tablicę. Moglibyśmy mieć przyimki portugalskie, hiszpańskie, włoskie i francuskie:glue ='de|da|del|dos|do|das|des|la|della|delli'.split('|');
Junior Mayhé
Nie zapewni to wielkich liter pierwszego słowa; tzn . and another thingstaje się and Another Thing. Potrzebujesz tylko eleganckiego sposobu, aby zawsze używać pierwszego słowa.
Brad Koch
@BradKoch - pad ze spacjami, więc używasz „i”, „de” itp. Jako słowa wyszukiwania, a następnie „And Another And Another” zamieni się na „And Another and Another”.
Yimin Rong
dobrze, z wyjątkiem tego, że wielką literą jest także tekst po 'i - podobnie jak H'Dy lub Number-One
luky 13.07.19
Zamiast używać operatora trójskładnikowego, możesz po prostu użyć rezerwowego: glue = glue || [„of”, „for”, „and”, „a”];
tm2josep
14

Jeśli regex użyty w powyższych rozwiązaniach powoduje dezorientację, wypróbuj ten kod:

function titleCase(str) {
  return str.split(' ').map(function(val){ 
    return val.charAt(0).toUpperCase() + val.substr(1).toLowerCase();
  }).join(' ');
}
immazharkhan
źródło
kocham to! brak konwersji na tablice.
neelmeg
1
uhhh ... split ma przekształcić go do tablicy, po prostu nie widzę go jako oczywisty, ponieważ mapoznacza, że nie trzeba używać []notacji
MalcolmOcean
2
Jest to to samo, co odpowiedź a8m sprzed 2 lat.
Michael - Where's Clay Shirky
1
Przerwy dla danych wejściowych z jednym znakiem.
Madbreaks,
1
@AlexChaffee sprawdź historię zmian. a8m nie użył funkcji strzałki w oryginalnej odpowiedzi.
Dziękuję
9

Stworzyłem tę funkcję, która może obsługiwać nazwiska (więc nie jest to przypadek tytułu), takie jak „McDonald” lub „MacDonald” lub „O'Toole” lub „D'Orazio”. Nie obsługuje jednak niemieckich ani holenderskich nazw z „van” lub „von”, które są często pisane małymi literami ... Wierzę, że „de” jest często małymi literami, np. „Robert de Niro”. Trzeba je jeszcze rozwiązać.

function toProperCase(s)
{
  return s.toLowerCase().replace( /\b((m)(a?c))?(\w)/g,
          function($1, $2, $3, $4, $5) { if($2){return $3.toUpperCase()+$4+$5.toUpperCase();} return $1.toUpperCase(); });
}
Lwangaman
źródło
1
+1 za rozpoznawanie nazw. Jednak nie obsługuje też poprawnie „macy”.
brianary
Była to jedyna funkcja, która poprawnie obsługiwała przekształcanie wielkich i małych liter na właściwe i zauważyła inicjały takie jak „Wyspy Dziewicze Stanów Zjednoczonych”.
Rodrigo Polo
Możesz obejść ten macyproblem, umieszczając w nim negatywne spojrzenie, tak więc \b((m)(a?c))?(\w)staje się\b((m)(a?c))?(\w)(?!\s)
Ste
8
var toMatch = "john w. smith";
var result = toMatch.replace(/(\w)(\w*)/g, function (_, i, r) {
      return i.toUpperCase() + (r != null ? r : "");
    }
)

Wydaje się, że działa ... Testowany z powyższym, „szybkobrązowy, lis? / Skacze / ^ ponad ^ leniwy! Pies ...” i „C: / pliki programów / jakiś dostawca / ich 2. aplikacja / a plik1.txt ”.

Jeśli chcesz 2Nd zamiast 2, możesz zmienić na /([a-z])(\w*)/g .

Pierwszy formularz można uprościć jako:

function toTitleCase(toTransform) {
  return toTransform.replace(/\b([a-z])/g, function (_, initial) {
      return initial.toUpperCase();
  });
}
PhiLho
źródło
7

Spróbuj tego

String.prototype.toProperCase = function(){
    return this.toLowerCase().replace(/(^[a-z]| [a-z]|-[a-z])/g, 
        function($1){
            return $1.toUpperCase();
        }
    );
};

Przykład

var str = 'john smith';
str.toProperCase();
Maxi Baez
źródło
7

Jeśli możesz używać bibliotek stron trzecich w swoim kodzie, lodash ma dla nas funkcję pomocniczą.

https://lodash.com/docs/4.17.3#startCase

_.startCase('foo bar');
// => 'Foo Bar'

_.startCase('--foo-bar--');
// => 'Foo Bar'
 
_.startCase('fooBar');
// => 'Foo Bar'
 
_.startCase('__FOO_BAR__');
// => 'FOO BAR'

waqas
źródło
7

Wypróbuj tę najkrótszą drogę:

str.replace(/(^[a-z])|(\s+[a-z])/g, txt => txt.toUpperCase());
Vikram
źródło
7

ES 6

str.split(' ')
   .map(s => s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase())
   .join(' ')

jeszcze

str.split(' ').map(function (s) {
    return s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase();
}).join(' ')
jssridhar
źródło
Tylko heads-up, prawdopodobnie powinno być, s.slice(0, 1).toUpperCase()jeśli nadal chcesz ten pierwszy list.
WindsofTime,
@jssridhar należy również poprawić kod w ES6.
caiosm1005,
1
str
Łamie,
@ jssridhar może być dla nas lepszy .charAt(0).toUpperCase().
roydukkey
2
duplikat odpowiedzi a8m
Dziękuję
6

Większość z tych odpowiedzi wydaje się ignorować możliwość użycia słowa metaznak granicy (\ b). Krótsza wersja wykorzystującej ją odpowiedzi Grega Deana:

function toTitleCase(str)
{
    return str.replace(/\b\w/g, function (txt) { return txt.toUpperCase(); });
}

Działa z nazwami dzielonymi, takimi jak Jim-Bob.

lewax00
źródło
2
Jest eleganckim rozwiązaniem częściowym, ale nie działa z ciągami akcentującymi lub dużymi literami. Dostaję „Sofía Vergara” => „SofíA Vergara” lub „Sofía VERGARA” => „SofíA VERGARA”. Drugi przypadek można rozwiązać za pomocą funkcji Apply .toLowerCase () przed .replace (...). Pierwszy przypadek musi znaleźć właściwe wyrażenie regularne.
Asereware
2
Hmm, to wydaje się być błędem w implementacji wyrażenia regularnego, pomyślałbym, że znaki akcentowane powinny być znakami słownymi (ale masz rację, ponieważ nie działa w takich przypadkach).
lewax00
\wzawiera tylko znaki [A-Za-z0-9_], a nie wszystkie litery. W tym celu musisz użyć kategorii Unicode \p{L}. Będziesz potrzebował /umodyfikatora (patrz tutaj ) i innego rozwiązania dla \b, które działa tylko pomiędzy \Wi \w(patrz tutaj )
cmbuckley,
6

Myślę, że najprostszym jest użycie css.

function format_str(str) {
    str = str.toLowerCase();
    return '<span style="text-transform: capitalize">'+ str +'</span>';
}
zastanawiać się
źródło
Zaktualizowałem kod i przetestowałem go. Powinno już działać.
zastanawiał się
Możesz używać CSS tylko we frakcji środowisk, w których jest używany JS, więc to rozwiązanie nie jest wykonalne. Za wszelką cenę należy unikać stylów wbudowanych.
Madbreaks,
5

Służy /\S+/gdo wspierania znaków diakrytycznych:

function toTitleCase(str) {
  return str.replace(/\S+/g, str => str.charAt(0).toUpperCase() + str.substr(1).toLowerCase());
}

console.log(toTitleCase("a city named örebro")); // A City Named Örebro

Jednak: „ s unshine ( y ellow)” ⇒ „ S unshine ( y ellow)”

le_m
źródło
5

Chciałem dodać własną odpowiedź, ponieważ potrzebowałem solidnej toTitleCasefunkcji, która uwzględnia wymienione tutaj reguły gramatyczne (artykuł polecany przez Google). Istnieją różne reguły, które zależą od długości ciągu wejściowego. Poniżej znajduje się funkcja + testy jednostkowe.

Ta funkcja również konsoliduje białe znaki i usuwa znaki specjalne (zmodyfikuj wyrażenie regularne według swoich potrzeb)

Funkcja toTitleCase

const toTitleCase = (str) => {
  const articles = ['a', 'an', 'the'];
  const conjunctions = ['for', 'and', 'nor', 'but', 'or', 'yet', 'so'];
  const prepositions = [
    'with', 'at', 'from', 'into','upon', 'of', 'to', 'in', 'for',
    'on', 'by', 'like', 'over', 'plus', 'but', 'up', 'down', 'off', 'near'
  ];

  // The list of spacial characters can be tweaked here
  const replaceCharsWithSpace = (str) => str.replace(/[^0-9a-z&/\\]/gi, ' ').replace(/(\s\s+)/gi, ' ');
  const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.substr(1);
  const normalizeStr = (str) => str.toLowerCase().trim();
  const shouldCapitalize = (word, fullWordList, posWithinStr) => {
    if ((posWithinStr == 0) || (posWithinStr == fullWordList.length - 1)) {
      return true;
    }

    return !(articles.includes(word) || conjunctions.includes(word) || prepositions.includes(word));
  }

  str = replaceCharsWithSpace(str);
  str = normalizeStr(str);

  let words = str.split(' ');
  if (words.length <= 2) { // Strings less than 3 words long should always have first words capitalized
    words = words.map(w => capitalizeFirstLetter(w));
  }
  else {
    for (let i = 0; i < words.length; i++) {
      words[i] = (shouldCapitalize(words[i], words, i) ? capitalizeFirstLetter(words[i], words, i) : words[i]);
    }
  }

  return words.join(' ');
}

Testy jednostkowe w celu zapewnienia poprawności

import { expect } from 'chai';
import { toTitleCase } from '../../src/lib/stringHelper';

describe('toTitleCase', () => {
  it('Capitalizes first letter of each word irrespective of articles, conjunctions or prepositions if string is no greater than two words long', function(){
    expect(toTitleCase('the dog')).to.equal('The Dog'); // Capitalize articles when only two words long
    expect(toTitleCase('for all')).to.equal('For All'); // Capitalize conjunctions when only two words long
    expect(toTitleCase('with cats')).to.equal('With Cats'); // Capitalize prepositions when only two words long
  });

  it('Always capitalize first and last words in a string irrespective of articles, conjunctions or prepositions', function(){
    expect(toTitleCase('the beautiful dog')).to.equal('The Beautiful Dog');
    expect(toTitleCase('for all the deadly ninjas, be it so')).to.equal('For All the Deadly Ninjas Be It So');
    expect(toTitleCase('with cats and dogs we are near')).to.equal('With Cats and Dogs We Are Near');
  });

  it('Replace special characters with space', function(){
    expect(toTitleCase('[wolves & lions]: be careful')).to.equal('Wolves & Lions Be Careful');
    expect(toTitleCase('wolves & lions, be careful')).to.equal('Wolves & Lions Be Careful');
  });

  it('Trim whitespace at beginning and end', function(){
    expect(toTitleCase(' mario & Luigi superstar saga ')).to.equal('Mario & Luigi Superstar Saga');
  });

  it('articles, conjunctions and prepositions should not be capitalized in strings of 3+ words', function(){
    expect(toTitleCase('The wolf and the lion: a tale of two like animals')).to.equal('The Wolf and the Lion a Tale of Two like Animals');
    expect(toTitleCase('the  three Musketeers  And plus ')).to.equal('The Three Musketeers and Plus');
  });
});

Pamiętaj, że usuwam sporo znaków specjalnych z podanych ciągów znaków. Konieczne będzie poprawienie wyrażenia regularnego w celu spełnienia wymagań Twojego projektu.

moment dipolowy
źródło
Wolę to rozwiązanie, ponieważ naprawdę zajmuje się tytułem. To nie jest „Przeminęło z wiatrem”, to „Przeminęło z wiatrem”
russellmania
5
"john f. kennedy".replace(/\b\S/g, t => t.toUpperCase())
Proximo
źródło
1
Działa z próbką i o'henryrobi dziwne rzeczy horse's mouth.
Michael - Where's Clay Shirky
"john f. kennEdy".toLowerCase().replace(/\b\S/g, t => t.toUpperCase())lepsze 🤔
w3debugger
Nie chciałem edytować odpowiedzi @ Proximo: \bi \Ssą specjalnymi klasami znaków oznaczającymi „granicę słów” i „pojedynczy znak spacji. Tak więc wyrażenie regularne dopasowuje każdy znak następujący po granicy słowa i dodaje ten znak wielką literą, stosując daną funkcję strzałki.
Jens
4

Korzystając z rozwiązania „lewax00”, stworzyłem to proste rozwiązanie, które wymusza „w” zaczynając od spacji lub „w”, które inicjują de słowo, ale nie jest w stanie usunąć dodatkowych spacji pośrednich.

"SOFÍA vergara".toLowerCase().replace(/\b(\s\w|^\w)/g, function (txt) { return txt.toUpperCase(); });

Rezultatem jest „Sofía Vergara”.

Asereware
źródło
4

Oto moja funkcja, która zajmuje się akcentowanymi znakami (ważnymi dla francuskiego!) I która może włączać / wyłączać obsługę niższych wyjątków. Mam nadzieję, że to pomaga.

String.prototype.titlecase = function(lang, withLowers = false) {
    var i, string, lowers, uppers;

    string = this.replace(/([^\s:\-'])([^\s:\-']*)/g, function(txt) {
        return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
    }).replace(/Mc(.)/g, function(match, next) {
        return 'Mc' + next.toUpperCase();
    });

    if (withLowers) {
        if (lang == 'EN') {
            lowers = ['A', 'An', 'The', 'At', 'By', 'For', 'In', 'Of', 'On', 'To', 'Up', 'And', 'As', 'But', 'Or', 'Nor', 'Not'];
        }
        else {
            lowers = ['Un', 'Une', 'Le', 'La', 'Les', 'Du', 'De', 'Des', 'À', 'Au', 'Aux', 'Par', 'Pour', 'Dans', 'Sur', 'Et', 'Comme', 'Mais', 'Ou', 'Où', 'Ne', 'Ni', 'Pas'];
        }
        for (i = 0; i < lowers.length; i++) {
            string = string.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'), function(txt) {
                return txt.toLowerCase();
            });
        }
    }

    uppers = ['Id', 'R&d'];
    for (i = 0; i < uppers.length; i++) {
        string = string.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), uppers[i].toUpperCase());
    }

    return string;
}
Ouatataz
źródło
4

Rozmawialiśmy tutaj, w biurze, i uważamy, że próba automatycznego poprawienia sposobu wprowadzania nazwisk w sposób, w jaki chcesz, jest obarczony potencjalnymi problemami.

Wymyśliliśmy kilka przypadków, w których różne rodzaje automatycznych wielkich liter rozpadają się i są one tylko dla angielskich nazw, każdy język ma swoją złożoność.

Problemy z pisaniem wielką literą każdej nazwy:

• Wprowadzanie akronimów takich jak IBM nie jest dozwolone, zmienia się w Ibm.

• Nazwa McDonald zmieni się w Mcdonald, co jest niepoprawne, to samo dotyczy MacDonald.

• Podwójnie nazwane nazwiska, takie jak Marie-Tonks, zamieniłyby się w Marie-tonks.

• Nazwy takie jak O'Connor zamieniłyby się w O'connor.

W przypadku większości z nich można napisać niestandardowe reguły, aby sobie z tym poradzić, jednak nadal występują problemy z akronimami, tak jak poprzednio, i pojawia się nowy problem:

• Dodanie reguły naprawy nazw w komputerach Mac, takich jak MacDonald, spowodowałoby, że nazwy przerwania, takie jak Macy, zamieniłyby je w MacY.

Jedynym wymyślonym przez nas rozwiązaniem, które nigdy nie jest niepoprawne, jest pisanie wielkimi literami, co jest metodą brutalnej siły, której wydaje się używać również DBS.

Więc jeśli chcesz zautomatyzować ten proces, najlepiej jest obejść się bez słownika dla każdej pojedynczej nazwy i słowa oraz tego, jak należy go używać wielkich liter. Jeśli nie masz reguły obejmującej wszystko, nie używaj jej w ten sposób po prostu zirytuje użytkowników i zachęci osoby, które chcą poprawnie wpisać swoje nazwisko, aby pójść gdzie indziej.

jjr2000
źródło
4

oto inne rozwiązanie za pomocą css (i javascript, jeśli tekst, który chcesz przekształcić, jest pisany wielkimi literami):

HTML

<span id='text'>JOHN SMITH</span>

js

var str = document.getElementById('text').innerHtml;
var return_text = str.toLowerCase();

css

#text{text-transform:capitalize;}
henrie
źródło
3

Dla tych z nas, którzy boją się wyrażeń regularnych (lol):

function titleCase(str)
{
    var words = str.split(" ");
    for ( var i = 0; i < words.length; i++ )
    {
        var j = words[i].charAt(0).toUpperCase();
        words[i] = j + words[i].substr(1);
    }
    return words.join(" ");
}

lashja
źródło
3

Moje jedno liniowe rozwiązanie:

String.prototype.capitalizeWords = function() {
    return this.split(" ").map(function(ele){ return ele[0].toUpperCase() + ele.slice(1).toLowerCase();}).join(" ");
};

Następnie możesz wywołać metodę capitalizeWords()na dowolnym ciągu. Na przykład:

var myS = "this actually works!";
myS.capitalizeWords();

>>> This Actually Works

Moje inne rozwiązanie:

function capitalizeFirstLetter(word) {
    return word[0].toUpperCase() + word.slice(1).toLowerCase();
}
String.prototype.capitalizeAllWords = function() {
    var arr = this.split(" ");
    for(var i = 0; i < arr.length; i++) {
        arr[i] = capitalizeFirstLetter(arr[i]);
    }
    return arr.join(" ");
};

Następnie możesz wywołać metodę capitalizeWords()na dowolnym ciągu. Na przykład:

var myStr = "this one works too!";
myStr.capitalizeWords();

>>> This One Works Too

Alternatywne rozwiązanie oparte na odpowiedzi Grega Deana:

function capitalizeFirstLetter(word) {
    return word[0].toUpperCase() + word.slice(1).toLowerCase();
}
String.prototype.capitalizeWords = function() {
    return this.replace(/\w\S*/g, capitalizeFirstLetter);
};

Następnie możesz wywołać metodę capitalizeWords()na dowolnym ciągu. Na przykład:

var myString = "yes and no";
myString.capitalizeWords()

>>> Yes And No
Fouad Boukredine
źródło
3

Zaskoczony, gdy nikt nie wspomniał o użyciu parametru rest. Oto prosty jednowarstwowy, który wykorzystuje parametry ES6 Rest.

let str="john smith"
str=str.split(" ").map(([firstChar,...rest])=>firstChar.toUpperCase()+rest.join("").toLowerCase()).join(" ")
console.log(str)

kapil pandey
źródło
2

Jest to oparte na moim rozwiązaniu FreeFodeCamp's Bonfire „Title Case” , które wymaga, aby najpierw przekonwertować podany ciąg znaków na wszystkie małe litery, a następnie przekonwertować każdą postać poprzedzającą spację na wielkie litery.

Bez użycia wyrażenia regularnego:

function titleCase(str) {
 return str.toLowerCase().split(' ').map(function(val) { return val.replace(val[0], val[0].toUpperCase()); }).join(' ');
}
Jamesy Dimmick May
źródło