Przekonwertuj camelCaseText na tekst przypadku zdania


144

Jak mogę przekonwertować ciąg, taki jak „helloThere” lub „HelloThere”, na „Hello There” w JavaScript?


9
hmm .. jaki jest twój oczekiwany wynik dla iLiveInTheUSA?
wim

8
Żyję w U ... o cholera! - Ale w moim przypadku mam ograniczony zestaw strun i nie ma takich, które mogłyby zepsuć prosty konwerter. Dobry chwyt!
HyderA

Podobnie uSBPort powinien dać w wyniku „USB Port”
signonsridhar

2
@wim: iLiveInTheUSA powinno być iLiveInTheUsa w prawidłowej notacji wielbłąda, ale to stwarzałoby inne problemy.
Konrad Höffner

Odpowiedzi:


187
var text = 'helloThereMister';
var result = text.replace( /([A-Z])/g, " $1" );
var finalResult = result.charAt(0).toUpperCase() + result.slice(1);
console.log(finalResult);

wielką literę - jako przykład.

Zwróć uwagę na spację w " $1".

EDYCJA: dodano przykład wielkiej pierwszej litery. Oczywiście, jeśli pierwsza litera jest już duża - miałbyś wolne miejsce do usunięcia.


1
Kopię użycie spacji text.replace, dopełniam wywołania funkcji 2+ argumentami spacjami również dla czytelności
rkd

8
uSBPorts => Porty USB, nie tego oczekuję, chcę porty USB
signonsridhar

a co z pisaniem Non-GoogleChrome?
Tim

107

Alternatywnie za pomocą lodash :

lodash.startCase(str);

Przykład:

_.startCase('helloThere');
// ➜ 'Hello There'

Lodash jest w porządku biblioteka dać skrót do wielu codziennych js tasks.There wiele innych podobnych funkcji ciąg manipulacji, takich jak camelCase, kebabCaseetc.


Jeśli spróbujesz, hello worldwyjście powinno wyglądać tak Hello There, w tym przypadku loadash nie będzie pomocny.
Abhishek Kumar

@AbhishekKumar startCase of lodash faktycznie zamieni się hello worldna Hello World lodash.com/docs/4.17.15#upperFirst
user1696017

Masz rację, bracie. Przez pomyłkę napisałem hello theredo hello world.
Abhishek Kumar

2
Za każdym razem, gdy myślę „nie ma mowy, żeby lodash też to robił”, tak właśnie jest.
efru

Uważaj od wersji 4 ta funkcja usuwa znaki specjalne, takie jak ä i konwertuje je na znaki ASCII (w tym przypadku)
kolega

52

Miałem podobny problem i poradziłem sobie z tym tak:

stringValue.replace(/([A-Z]+)*([A-Z][a-z])/g, "$1 $2")

Aby uzyskać bardziej solidne rozwiązanie:

stringValue.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1")

http://jsfiddle.net/PeYYQ/

Wejście:

 helloThere 
 HelloThere 
 ILoveTheUSA
 iLoveTheUSA

Wynik:

 hello There 
 Hello There 
 I Love The USA
 i Love The USA

daje dodatkową przestrzeń na starcie
hannad rehman

4
To nie jest przypadek zdaniowy, jak pytał OP. Pierwsza litera powinna być wielka.
H Dog

Ponadto dodaje dodatkową spację między słowami
Alacritas

34

Przykład bez skutków ubocznych.

function camel2title(camelCase) {
  // no side-effects
  return camelCase
    // inject space before the upper case letters
    .replace(/([A-Z])/g, function(match) {
       return " " + match;
    })
    // replace first char with upper case
    .replace(/^./, function(match) {
      return match.toUpperCase();
    });
}

W ES6

const camel2title = (camelCase) => camelCase
  .replace(/([A-Z])/g, (match) => ` ${match}`)
  .replace(/^./, (match) => match.toUpperCase());

1
Solidne, +1 dla fragmentu es6.
BradStell

4
FYI, to dodaje dodatkowe białe znaki na początku zdania.
Dale Zak,

20

Najlepszym ciągiem, jaki znalazłem do testowania funkcji z wielbłąda do przypadku, jest ten absurdalnie bezsensowny przykład, który testuje wiele przypadków skrajnych. O ile wiem, żadna z wcześniej opublikowanych funkcji nie obsługuje tego poprawnie :

ToGet YourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D

Należy to przekonwertować na:

Aby uzyskać GED na czas Piosenka o 26 ABC jest najważniejsza, ale osobisty dowód tożsamości dla użytkownika 456 w pokoju 26A zawierający ABC 26 razy nie jest tak łatwy jak 123 dla C3PO lub R2D2 lub 2R2D

Jeśli potrzebujesz tylko prostej funkcji, która obsługuje przypadki takie jak ta powyżej (i więcej przypadków niż wiele wcześniejszych odpowiedzi), oto ta, którą napisałem. Ten kod nie jest szczególnie elegancki ani szybki, ale jest prosty, zrozumiały i działa.

Przykład do uruchomienia online znajduje się na jsfiddle lub możesz wyświetlić dane wyjściowe fragmentu kodu poniżej w konsoli:

// Take a single camel case string and convert it to a string of separate words (with spaces) at the camel-case boundaries.
// 
// E.g.:
var examples = [
    'ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D',
    //                                          --> To Get Your GED In Time A Song About The 26 ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D
    'helloThere', //                              --> Hello There
    'HelloThere', //                              --> Hello There
    'ILoveTheUSA', //                             --> I Love The USA
    'iLoveTheUSA', //                             --> I Love The USA
    'DBHostCountry', //                           --> DB Host Country
    'SetSlot123ToInput456', //                    --> Set Slot 123 To Input 456
    'ILoveTheUSANetworkInTheUSA', //              --> I Love The USA Network In The USA
    'Limit_IOC_Duration', //                      --> Limit IOC Duration
    'This_is_a_Test_of_Network123_in_12_days', // --> This Is A Test Of Network 123 In 12 Days
    'ASongAboutTheABCsIsFunToSing', //            --> A Song About The ABCs Is Fun To Sing
    'CFDs', //                                    --> CFDs
    'DBSettings', //                              --> DB Settings
    'IWouldLove1Apple', //                        --> 1 Would Love 1 Apple
    'Employee22IsCool', //                        --> Employee 22 Is Cool
    'SubIDIn', //                                 --> Sub ID In
    'ConfigureCFDsImmediately', //                --> Configure CFDs Immediately
    'UseTakerLoginForOnBehalfOfSubIDInOrders', // --> Use Taker Login For On Behalf Of Sub ID In Orders
]

function camelCaseToTitleCase(in_camelCaseString) {
        var result = in_camelCaseString                         // "ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D"
            .replace(/([a-z])([A-Z][a-z])/g, "$1 $2")           // "To Get YourGEDIn TimeASong About The26ABCs IsOf The Essence ButAPersonalIDCard For User456In Room26AContainingABC26Times IsNot AsEasy As123ForC3POOrR2D2Or2R2D"
            .replace(/([A-Z][a-z])([A-Z])/g, "$1 $2")           // "To Get YourGEDIn TimeASong About The26ABCs Is Of The Essence ButAPersonalIDCard For User456In Room26AContainingABC26Times Is Not As Easy As123ForC3POOr R2D2Or2R2D"
            .replace(/([a-z])([A-Z]+[a-z])/g, "$1 $2")          // "To Get Your GEDIn Time ASong About The26ABCs Is Of The Essence But APersonal IDCard For User456In Room26AContainingABC26Times Is Not As Easy As123ForC3POOr R2D2Or2R2D"
            .replace(/([A-Z]+)([A-Z][a-z][a-z])/g, "$1 $2")     // "To Get Your GEDIn Time A Song About The26ABCs Is Of The Essence But A Personal ID Card For User456In Room26A ContainingABC26Times Is Not As Easy As123ForC3POOr R2D2Or2R2D"
            .replace(/([a-z]+)([A-Z0-9]+)/g, "$1 $2")           // "To Get Your GEDIn Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456In Room 26A Containing ABC26Times Is Not As Easy As 123For C3POOr R2D2Or 2R2D"
            
            // Note: the next regex includes a special case to exclude plurals of acronyms, e.g. "ABCs"
            .replace(/([A-Z]+)([A-Z][a-rt-z][a-z]*)/g, "$1 $2") // "To Get Your GED In Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456In Room 26A Containing ABC26Times Is Not As Easy As 123For C3PO Or R2D2Or 2R2D"
            .replace(/([0-9])([A-Z][a-z]+)/g, "$1 $2")          // "To Get Your GED In Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456In Room 26A Containing ABC 26Times Is Not As Easy As 123For C3PO Or R2D2Or 2R2D"  

            // Note: the next two regexes use {2,} instead of + to add space on phrases like Room26A and 26ABCs but not on phrases like R2D2 and C3PO"
            .replace(/([A-Z]{2,})([0-9]{2,})/g, "$1 $2")        // "To Get Your GED In Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D"
            .replace(/([0-9]{2,})([A-Z]{2,})/g, "$1 $2")        // "To Get Your GED In Time A Song About The 26 ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D"
            .trim();


  // capitalize the first letter
  return result.charAt(0).toUpperCase() + result.slice(1);
}

examples.forEach(str => console.log(str, ' --> \n', camelCaseToTitleCase(str)));


11

Na podstawie jednego z powyższych przykładów wymyśliłem to:

const camelToTitle = (camelCase) => camelCase
  .replace(/([A-Z])/g, (match) => ` ${match}`)
  .replace(/^./, (match) => match.toUpperCase())
  .trim()

Działa dla mnie, ponieważ używa .trim()do obsługi przypadku krawędzi, w którym pierwsza litera jest wielka, a kończy się dodatkową spacją wiodącą.

Źródła: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim


10

Ok, spóźniłem się o kilka lat do gry, ale miałem podobne pytanie i chciałem zrobić jedno zastępcze rozwiązanie dla każdego możliwego wejścia. Większość zasług należy przypisać @ZenMaster w tym wątku i @Benjamin Udink ten Cate w tym wątku. Oto kod:

var camelEdges = /([A-Z](?=[A-Z][a-z])|[^A-Z](?=[A-Z])|[a-zA-Z](?=[^a-zA-Z]))/g;
var textArray = ["lowercase",
                 "Class",
                 "MyClass",
                 "HTML",
                 "PDFLoader",
                 "AString",
                 "SimpleXMLParser",
                 "GL11Version",
                 "99Bottles",
                 "May5",
                 "BFG9000"];
var text;
var resultArray = [];
for (var i = 0; i < a.length; i++){
    text = a[i];
    text = text.replace(camelEdges,'$1 ');
    text = text.charAt(0).toUpperCase() + text.slice(1);
    resultArray.push(text);
}

Zawiera trzy klauzule, z których wszystkie używają lookahead, aby silnik regex nie zużywał zbyt wielu znaków:

  1. [A-Z](?=[A-Z][a-z])szuka dużej litery, po której następuje wielka, a następnie mała litera. To koniec akronimów takich jak USA.
  2. [^A-Z](?=[A-Z])szuka litery innej niż duża, po której następuje duża litera. To kończy słowa takie jak myWord i symbole takie jak 99Bottles.
  3. [a-zA-Z](?=[^a-zA-Z])szuka litery, po której następuje nieliter. To kończy słowa przed symbolami takimi jak BFG9000.

To pytanie było u góry moich wyników wyszukiwania, więc mam nadzieję, że zaoszczędzę innym trochę czasu!


9

Oto moja wersja. Dodaje spację przed każdą angielską literą UpperCase, która występuje po małej angielskiej literze, a także w razie potrzeby zamienia wielką literę na wielką:

Na przykład:
thisIsCamelCase -> This Is Camel Case
this IsCamelCase -> This Is Camel Case
thisIsCamelCase123 -> This Is Camel Case123

  function camelCaseToTitleCase(camelCase){
    if (camelCase == null || camelCase == "") {
      return camelCase;
    }

    camelCase = camelCase.trim();
    var newText = "";
    for (var i = 0; i < camelCase.length; i++) {
      if (/[A-Z]/.test(camelCase[i])
          && i != 0
          && /[a-z]/.test(camelCase[i-1])) {
        newText += " ";
      }
      if (i == 0 && /[a-z]/.test(camelCase[i]))
      {
        newText += camelCase[i].toUpperCase();
      } else {
        newText += camelCase[i];
      }
    }

    return newText;
  }

6

Ta implementacja bierze pod uwagę kolejne wielkie litery i cyfry.

function camelToTitleCase(str) {
  return str
    .replace(/[0-9]{2,}/g, match => ` ${match} `)
    .replace(/[^A-Z0-9][A-Z]/g, match => `${match[0]} ${match[1]}`)
    .replace(/[A-Z][A-Z][^A-Z0-9]/g, match => `${match[0]} ${match[1]}${match[2]}`)
    .replace(/[ ]{2,}/g, match => ' ')
    .replace(/\s./g, match => match.toUpperCase())
    .replace(/^./, match => match.toUpperCase())
    .trim();
}

// ----------------------------------------------------- //

var testSet = [
    'camelCase',
    'camelTOPCase',
    'aP2PConnection',
    'superSimpleExample',
    'aGoodIPAddress',
    'goodNumber90text',
    'bad132Number90text',
];

testSet.forEach(function(item) {
    console.log(item, '->', camelToTitleCase(item));
});

Oczekiwany wynik:

camelCase -> Camel Case
camelTOPCase -> Camel TOP Case
aP2PConnection -> A P2P Connection
superSimpleExample -> Super Simple Example
aGoodIPAddress -> A Good IP Address
goodNumber90text -> Good Number 90 Text
bad132Number90text -> Bad 132 Number 90 Text

Użyłbym odpowiedzi Chrisa Kline'a, która uwzględnia ciągi takie jak „Adres IP” (gdzie ta funkcja zamienia ją na „Adres IP”
John Hamm

@JohnHamm Twoje dane wejściowe to „Adres IP”, prawda? To nie jest przypadek wielbłąda! Przeczytaj o tym, czym jest obudowa wielbłąda: en.wikipedia.org/wiki/Camel_case Nie umieszczaj spacji między i wprowadzaj tylko „adres IP”. Ta funkcja działa dobrze.
Dipu

3

Możesz użyć takiej funkcji:

function fixStr(str) {
    var out = str.replace(/^\s*/, "");  // strip leading spaces
    out = out.replace(/^[a-z]|[^\s][A-Z]/g, function(str, offset) {
        if (offset == 0) {
            return(str.toUpperCase());
        } else {
            return(str.substr(0,1) + " " + str.substr(1).toUpperCase());
        }
    });
    return(out);
}

"hello World" ==> "Hello World"
"HelloWorld" ==> "Hello World"
"FunInTheSun" ==? "Fun In The Sun"

Kod z wieloma ciągami testowymi tutaj: http://jsfiddle.net/jfriend00/FWLuV/ .

Alternatywna wersja, która zachowuje wiodące spacje tutaj: http://jsfiddle.net/jfriend00/Uy2ac/ .


Wiem, że to nie było wymaganie w pytaniu, ale na przykład twoje rozwiązanie nie działa " helloWorld".
ZenMaster

Tak, to nowy wymóg. Próbowałem zrobić dokładnie to, o co prosiłeś. W każdym razie, skrótem łatwo jest oddzielić wiodące spacje, jeśli i tak ich tam nie potrzebujesz. Gdybyś chciał, żeby zostały na miejscu, to też można by zrobić.
jfriend00

Oto jsFiddle, który pokazuje metodę, która działa z nowym wymaganiem „helloWorld” i zachowuje wiodącą spację (jeśli chcesz): jsfiddle.net/jfriend00/Uy2ac .
jfriend00

Miły. Zastanawiam się jednak, jak to działa. Funkcja handlera będzie wywoływana przy każdym dopasowaniu, prawda?
ZenMaster

Jeśli robisz zyliony z nich w ustawieniach wrażliwych na wydajność, wymagałoby trochę testów jsperf w kilku przeglądarkach, aby zobaczyć, jakie byłoby najszybsze rozwiązanie. Oddzwonienie to nic wielkiego. Wyrażenia regularne każdego rodzaju rzadko są najszybszym rozwiązaniem w porównaniu z kodem specjalnego przeznaczenia, ale pozwalają zaoszczędzić dużo kodu (i często kilka błędów), więc często są pożądanym wyborem. To zależy od twoich wymagań.
jfriend00

3

wypróbuj tę bibliotekę

http://sugarjs.com/api/String/titleize

'man from the boondocks'.titleize()>"Man from the Boondocks"
'x-men: the last stand'.titleize()>"X Men: The Last Stand"
'TheManWithoutAPast'.titleize()>"The Man Without a Past"
'raiders_of_the_lost_ark'.titleize()>"Raiders of the Lost Ark"

2

Żadna z powyższych odpowiedzi nie działała idealnie dla mnie, więc musiałem przyjechać z własnym rowerem:

function camelCaseToTitle(camelCase) {
    if (!camelCase) {
        return '';
    }

    var pascalCase = camelCase.charAt(0).toUpperCase() + camelCase.substr(1);
    return pascalCase
        .replace(/([a-z])([A-Z])/g, '$1 $2')
        .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')
        .replace(/([a-z])([0-9])/gi, '$1 $2')
        .replace(/([0-9])([a-z])/gi, '$1 $2');
}

Przypadki testowe:

null => ''
'' => ''
'simpleString' => 'Simple String'
'stringWithABBREVIATIONInside => 'String With ABBREVIATION Inside'
'stringWithNumber123' => 'String With Number 123'
'complexExampleWith123ABBR890Etc' => 'Complex Example With 123 ABBR 890 Etc'

2

To działa dla mnie, sprawdź to

CamelcaseToWord ("MyName"); // zwraca Moje imię

    function CamelcaseToWord(string){
      return string.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1");
    }

1
Witamy w SO :) Dodaj co najmniej jedną linię wyjaśniającą do swojego kodu. Upewnij się również, że jest to Twoja praca intelektualna lub zacytuj źródła.
Lorenz Lo Sauer

Należy usunąć spację w ostatniej „$ 1”. string.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, "$1");
Valeria Shpiner


2

Jeśli masz do czynienia z Capital Camel Case, ten fragment może ci pomóc, zawiera również pewne specyfikacje, dzięki czemu możesz być pewien, że pasuje do twojego przypadku.

export const fromCamelCaseToSentence = (word) =>
  word
    .replace(/([A-Z][a-z]+)/g, ' $1')
    .replace(/([A-Z]{2,})/g, ' $1')
    .replace(/\s{2,}/g, ' ')
    .trim();

I specyfikacje:

describe('fromCamelCaseToSentence', () => {
 test('does not fall with a single word', () => {
   expect(fromCamelCaseToSentence('Approved')).toContain('Approved')
   expect(fromCamelCaseToSentence('MDA')).toContain('MDA')
 })

 test('does not fall with an empty string', () => {
   expect(fromCamelCaseToSentence('')).toContain('')
 })

 test('returns the separated by space words', () => {
   expect(fromCamelCaseToSentence('NotApprovedStatus')).toContain('Not Approved Status')
   expect(fromCamelCaseToSentence('GDBState')).toContain('GDB State')
   expect(fromCamelCaseToSentence('StatusDGG')).toContain('Status DGG')
 })
})

1

Nie wypróbowałem odpowiedzi wszystkich, ale kilka rozwiązań, przy których majstrowałem, nie spełniało wszystkich moich wymagań.

Udało mi się wymyślić coś, co ...

export const jsObjToCSSString = (o={}) =>
    Object.keys(o)
          .map(key => ({ key, value: o[key] }))
          .map(({key, value}) =>
              ({
                key: key.replace( /([A-Z])/g, "-$1").toLowerCase(),
                value
              })
          )
          .reduce(
              (css, {key, value}) => 
                  `${css} ${key}: ${value}; `.trim(), 
              '')

1

Poniżej znajduje się link, który demonstruje ciąg znaków wielbłąda w ciągu zdań przy użyciu wyrażenia regularnego.

Wejście

myCamelCaseSTRINGToSPLITDemo

Wynik

my Camel Case STRING To SPLIT Demo


To jest wyrażenie regularne do konwersji wielkości wielbłąda na tekst zdania

(?=[A-Z][a-z])|([A-Z]+)([A-Z][a-rt-z][a-z]\*)

z $1 $2jak subsitution.

Kliknij, aby wyświetlić konwersję na wyrażeniu regularnym


W treści odpowiedzi podaj odpowiednią treść z linku.
Grant Miller

1

Wprowadź javaScript

Wyjście Java Script

   var text = 'javaScript';
    text.replace(/([a-z])([A-Z][a-z])/g, "$1 $2").charAt(0).toUpperCase()+text.slice(1).replace(/([a-z])([A-Z][a-z])/g, "$1 $2");

1

Jeszcze jedno rozwiązanie oparte na RegEx.

respace(str) {
  const regex = /([A-Z])(?=[A-Z][a-z])|([a-z])(?=[A-Z])/g;
  return str.replace(regex, '$& ');
}

Wyjaśnienie

Powyższe wyrażenie regularne składa się z dwóch podobnych części oddzielonych operatorem OR . Pierwsza połowa:

  1. ([A-Z]) - dopasowuje wielkie litery ...
  2. (?=[A-Z][a-z]) - po którym następuje sekwencja wielkich i małych liter.

Po zastosowaniu do sekwencji FOo , efektownie pasuje do jej litery F.

Lub drugi scenariusz:

  1. ([a-z]) - dopasowuje małe litery ...
  2. (?=[A-Z]) - po której następuje wielka litera.

Po zastosowaniu do sekwencji barFoo , efektywnie dopasowuje to literę r .

Po znalezieniu wszystkich kandydatów do zamiany ostatnią rzeczą do zrobienia jest zastąpienie ich tą samą literą, ale dodatkową spacją. W tym celu możemy użyć go '$& 'jako zamiennika i zostanie rozwiązany do dopasowanego podciągu, po którym następuje znak spacji.

Przykład

const regex = /([A-Z])(?=[A-Z][a-z])|([a-z])(?=[A-Z])/g
const testWords = ['ACoolExample', 'fooBar', 'INAndOUT', 'QWERTY', 'fooBBar']

testWords.map(w => w.replace(regex, '$& '))
->(5) ["A Cool Example", "foo Bar", "IN And OUT", "QWERTY", "foo B Bar"]

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.