Przekształcenie dowolnego sznurka w wielbłąd

171

Jak mogę przekształcić ciąg znaków w skrzynkę wielbłąda za pomocą wyrażenia regularnego javascript?

EquipmentClass namelub Equipment classNamelub equipment class namelubEquipment Class Name

powinny stać się: equipmentClassName.

Scott Klarenbach
źródło
1
Zrobiłem jsperf próbę różnymi metodami. wyniki były nieco niejednoznaczne. wydaje się, że zależy od ciągu wejściowego.
yincrash
Nowy test jsperf z kilkoma różnymi ciągami do przetestowania i szerszą gamą implementacji: jsperf.com/camel-casing-regexp-or-character-manipulation/1 - to prowadzi mnie do wniosku, że dla przeciętnego przypadku pomimo frazowanie przez pytającego tego pytania, wyrażenia regularne nie są tym, czego chcesz. Są nie tylko znacznie trudniejsze do zrozumienia, ale także (przynajmniej w przypadku aktualnych wersji Chrome) ich działanie zajmuje około dwa razy dłużej.
Jules

Odpowiedzi:

237

Patrząc na swój kod, możesz to osiągnąć za pomocą tylko dwóch replacewywołań:

function camelize(str) {
  return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function(word, index) {
    return index === 0 ? word.toLowerCase() : word.toUpperCase();
  }).replace(/\s+/g, '');
}

camelize("EquipmentClass name");
camelize("Equipment className");
camelize("equipment class name");
camelize("Equipment Class Name");
// all output "equipmentClassName"

Edycja: Lub za pomocą jednego replacepołączenia, przechwytując białe spacje również w RegExp.

function camelize(str) {
  return str.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function(match, index) {
    if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces
    return index === 0 ? match.toLowerCase() : match.toUpperCase();
  });
}
CMS
źródło
4
Świetny kod i ostatecznie wygrał jsperf.com/js-camelcase/5 . Chcesz udostępnić wersję, która może obsługiwać (usuwać) znaki inne niż alfa? camelize("Let's Do It!") === "let'SDoIt!" smutna twarz . Spróbuję sam, ale obawiam się, że dodam kolejny zamiennik.
Orwellophile
2
.. ponieważ nie alfa nie powinno wpływać na sprawę, nie jestem pewien, czy da się to zrobić lepiej niż return this.replace(/[^a-z ]/ig, '').replace(/(?:^\w|[A-Z]|\b\w|\s+)/g,...
Orwellophile
4
Dla moich przyjaciół z ES2015 +: jedna linijka oparta na powyższym kodzie. const toCamelCase = (str) => str.replace(/(?:^\w|[A-Z]|\b\w)/g, (ltr, idx) => idx === 0 ? ltr.toLowerCase() : ltr.toUpperCase()).replace(/\s+/g, '');
tabrindle
2
Chociaż nie był to przypadek zadawany przykładowo, innym typowym wejściem, które prawdopodobnie zobaczysz, jest „NAZWA KLASY SPRZĘTU”, dla której ta metoda zawodzi.
Alexander Tsepkov
1
@EdmundReed możesz po prostu zamienić cały ciąg na małe litery przed zamianą na wielkość liter wielbłąda, łącząc .toLowerCase()metodę w łańcuch . Np. używając rozwiązania @ tabrindle powyżej:const toCamelCase = (str) => str.toLowerCase().replace(/(?:^\w|[A-Z]|\b\w)/g, (ltr, idx) => idx === 0 ? ltr.toLowerCase() : ltr.toUpperCase()).replace(/\s+/g, '');
bitfidget,
102

Jeśli ktoś używa lodash , jest _.camelCase()funkcja.

_.camelCase('Foo Bar');
// → 'fooBar'

_.camelCase('--foo-bar--');
// → 'fooBar'

_.camelCase('__FOO_BAR__');
// → 'fooBar'
d4nyll
źródło
2
Ta odpowiedź zdecydowanie powinna pojawić się dalej. Lodash zapewnia kompletny zestaw do konwersji łańcuchów między różnymi przypadkami.
btx
55

Skończyło się na tym:

String.prototype.toCamelCase = function(str) {
    return str
        .replace(/\s(.)/g, function($1) { return $1.toUpperCase(); })
        .replace(/\s/g, '')
        .replace(/^(.)/, function($1) { return $1.toLowerCase(); });
}

Próbowałem uniknąć łączenia w łańcuch wielu instrukcji zamiany. Coś, gdzie w mojej funkcji miałbym 1 $, 2 $, 3 $. Ale ten typ grupowania jest trudny do zrozumienia, a twoja wzmianka o problemach z różnymi przeglądarkami jest czymś, o czym nigdy też nie myślałem.

Scott Klarenbach
źródło
1
Dla mnie wygląda dobrze i nic nie wygląda podejrzanie, jeśli chodzi o problemy z różnymi przeglądarkami. (Nie żebym był super-ekspertem czy kimkolwiek innym.)
Pointy
47
Jeśli zamierzasz użyć String.prototype, dlaczego nie użyć po prostu „this” zamiast wysyłać parametr „str”?
yincrash
6
Aby uzyskać lepszą kompatybilność z przeglądarką, użyj tego zamiast str (i usuń parametr z wywołania funkcji)
João Paulo Motta
2
Wystarczy użyć this.valueOf()zamiast zdawać str. Alternatywnie (tak jak w moim przypadku), this.toLowerCase()ponieważ moje ciągi wejściowe były zapisane WIELKIMI LITERAMI, które nie miały odpowiednio zmniejszonych części bez garbu. Użycie po prostu thiszwraca sam obiekt string, który w rzeczywistości jest tablicą znaków, stąd wspomniany powyżej błąd TypeError.
Draco18s nie ufa już SE
2
To daje dokładne przeciwieństwo tego, co jest potrzebne. To zwróci STRING.
Awol
41

Możesz skorzystać z tego rozwiązania:

function toCamelCase(str){
  return str.split(' ').map(function(word,index){
    // If it is the first word make sure to lowercase all the chars.
    if(index == 0){
      return word.toLowerCase();
    }
    // If it is not the first word only upper case the first char and lowercase the rest.
    return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
  }).join('');
}
ismnoiet
źródło
To jest wielkie litery, a nie wielbłąd.
nikk wong
2
Wielbłąd to pierwszy znak każdego słowa w dużej wielkości, a toCamelCasefunkcja po prostu to robi.
ismnoiet
2
Myślisz o PascalCase . CamelCase może być wielkimi lub małymi literami. W tym kontekście często stosuje się małe litery, aby uniknąć nieporozumień.
Kody
1
Dzięki @Kody, @ cchamberlain za konstruktywny komentarz, sprawdź zaktualizowaną wersję.
ismnoiet
5
+1, aby nie używać wyrażeń regularnych, nawet jeśli pytanie dotyczyło rozwiązania wykorzystującego je. Jest to znacznie jaśniejsze rozwiązanie, a także wyraźna korzyść dla wydajności (ponieważ przetwarzanie złożonych wyrażeń regularnych jest znacznie trudniejszym zadaniem niż zwykłe iterowanie po kilku ciągach i łączenie ich razem). Zobacz jsperf.com/camel-casing-regexp-or-character-manipulation/1, gdzie razem z tym razem wziąłem kilka przykładów (a także moje własne skromne ulepszenie go pod kątem wydajności, chociaż prawdopodobnie wolałbym to wersji dla zachowania przejrzystości w większości przypadków).
Jules
40

Aby uzyskać c amel C ase

ES5

var camalize = function camalize(str) {
    return str.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, function(match, chr)
    {
        return chr.toUpperCase();
    });
}

ES6

var camalize = function camalize(str) {
    return str.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());
}


Aby uzyskać C amel S entence C ase lub P ascal C ase

var camelSentence = function camelSentence(str) {
    return  (" " + str).toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, function(match, chr)
    {
        return chr.toUpperCase();
    });
}

Uwaga:
dla tych języków z akcentami. Dołącz À-ÖØ-öø-ÿdo wyrażenia regularnego w następujący sposób
.replace(/[^a-zA-ZÀ-ÖØ-öø-ÿ0-9]+(.)/g

uśmiechnięta twarz
źródło
3
Najlepsza odpowiedź tutaj - czysta i zwięzła.
codeepic
5
ES6 zrobiło dla mnie wszystko małymi literami
C Bauer
@Luis dodał https://stackoverflow.com/posts/52551910/revisionsES6, nie testowałem tego. Sprawdzę i zaktualizuję.
smilyface
Nie działa dla słów z akcentami jsbin.com/zayafedubo/edit?js,console
Manuel Ortiz
1
nie zadziała, jeśli przekażesz kamelizowany sznur. Musimy sprawdzić, czy mamy już zakamalizowaną strunę.
Sheikh Abdul Wahid
27

W konkretnym przypadku Scotta wybrałbym coś takiego:

String.prototype.toCamelCase = function() {
    return this.replace(/^([A-Z])|\s(\w)/g, function(match, p1, p2, offset) {
        if (p2) return p2.toUpperCase();
        return p1.toLowerCase();        
    });
};

'EquipmentClass name'.toCamelCase()  // -> equipmentClassName
'Equipment className'.toCamelCase()  // -> equipmentClassName
'equipment class name'.toCamelCase() // -> equipmentClassName
'Equipment Class Name'.toCamelCase() // -> equipmentClassName

Wyrażenie regularne dopasuje pierwszy znak, jeśli zaczyna się wielką literą i dowolnym znakiem alfabetu występującym po spacji, tj. 2 lub 3 razy w określonych ciągach.

/^([A-Z])|[\s-_](\w)/gDoprawienie wyrażenia regularnego spowoduje również kamelizację nazw typów łączników i podkreślników.

'hyphen-name-format'.toCamelCase()     // -> hyphenNameFormat
'underscore_name_format'.toCamelCase() // -> underscoreNameFormat
Fredric
źródło
co, jeśli w ciągu znaków jest więcej niż 2,3 myślników lub podkreślników, takich jak .data-nazwa-produktu, .data-opis-produktu, .product-container__actions - price, .photo-placeholder__photo
Ashwani Shukla
1
@AshwaniShukla Aby obsłużyć wiele łączników i / lub podkreśleń, będziesz musiał dodać mnożnik ( +) do grupy znaków, tj .:/^([A-Z])|[\s-_]+(\w)/g
Fredric
21
function toCamelCase(str) {
  // Lower cases the string
  return str.toLowerCase()
    // Replaces any - or _ characters with a space 
    .replace( /[-_]+/g, ' ')
    // Removes any non alphanumeric characters 
    .replace( /[^\w\s]/g, '')
    // Uppercases the first character in each group immediately following a space 
    // (delimited by spaces) 
    .replace( / (.)/g, function($1) { return $1.toUpperCase(); })
    // Removes spaces 
    .replace( / /g, '' );
}

Próbowałem znaleźć funkcję JavaScript camelCasew łańcuchu i chciałem się upewnić, że znaki specjalne zostaną usunięte (i miałem problem ze zrozumieniem, co robią niektóre z powyższych odpowiedzi). Jest to oparte na odpowiedzi cc young, z dodanymi komentarzami i usunięciem znaków $ peci & l.

Eilidh
źródło
10

Niezawodny, działający przykład, z którego korzystam od lat:

function camelize(text) {
    text = text.replace(/[-_\s.]+(.)?/g, (_, c) => c ? c.toUpperCase() : '');
    return text.substr(0, 1).toLowerCase() + text.substr(1);
}

Znaki zmieniające wielkość liter:

  • łącznik -
  • podkreślać _
  • Kropka .
  • przestrzeń
Vitaly-t
źródło
9

Jeśli regexp nie jest wymagane, możesz spojrzeć na następujący kod, który stworzyłem dawno temu dla Twinkle :

String.prototype.toUpperCaseFirstChar = function() {
    return this.substr( 0, 1 ).toUpperCase() + this.substr( 1 );
}

String.prototype.toLowerCaseFirstChar = function() {
    return this.substr( 0, 1 ).toLowerCase() + this.substr( 1 );
}

String.prototype.toUpperCaseEachWord = function( delim ) {
    delim = delim ? delim : ' ';
    return this.split( delim ).map( function(v) { return v.toUpperCaseFirstChar() } ).join( delim );
}

String.prototype.toLowerCaseEachWord = function( delim ) {
    delim = delim ? delim : ' ';
    return this.split( delim ).map( function(v) { return v.toLowerCaseFirstChar() } ).join( delim );
}

Nie wykonałem żadnych testów wydajności, a wersje regexp mogą być szybsze lub nie.

azatoth
źródło
Średnio 5 razy szybciej, jeśli potrzebujesz tylko 1 słowa jsbin.com/wuvagenoka/edit?html,js,output
Omu
8

Moje podejście do ES6 :

const camelCase = str => {
  let string = str.toLowerCase().replace(/[^A-Za-z0-9]/g, ' ').split(' ')
                  .reduce((result, word) => result + capitalize(word.toLowerCase()))
  return string.charAt(0).toLowerCase() + string.slice(1)
}

const capitalize = str => str.charAt(0).toUpperCase() + str.toLowerCase().slice(1)

let baz = 'foo bar'
let camel = camelCase(baz)
console.log(camel)  // "fooBar"
camelCase('foo bar')  // "fooBar"
camelCase('FOO BAR')  // "fooBar"
camelCase('x nN foo bar')  // "xNnFooBar"
camelCase('!--foo-¿?-bar--121-**%')  // "fooBar121"
eledgaar
źródło
A co z imionami takimi jak Jean-Pierre?
Max Alexander Hanna
5
return "hello world".toLowerCase().replace(/(?:(^.)|(\s+.))/g, function(match) {
    return match.charAt(match.length-1).toUpperCase();
}); // HelloWorld
Judzhin Miles
źródło
5

lodash może załatwić sprawę pewnie i dobrze:

var _ = require('lodash');
var result = _.camelCase('toto-ce héros') 
// result now contains "totoCeHeros"

Chociaż lodashmoże to być „duża” biblioteka (~ 4kB), zawiera ona wiele funkcji, do których normalnie używałbyś fragmentu kodu lub tworzyłbyś go samodzielnie.

Alain Beauvois
źródło
istnieją moduły npm z każdą indywidualną funkcją lodash, więc nie musisz importować całej "dużej" biblioteki: npmjs.com/package/lodash.camelcase
gion_13
5

Oto jeden liner wykonujący pracę:

const camelCaseIt = string => string.toLowerCase().trim().split(/[.\-_\s]/g).reduce((string, word) => string + word[0].toUpperCase() + word.slice(1));

Dzieli ciąg z małymi literami na podstawie listy znaków podanej w wyrażeniu regularnym [.\-_\s] (dodaj więcej wewnątrz []!) I zwraca tablicę słów. Następnie redukuje tablicę ciągów do jednego połączonego ciągu słów z dużymi pierwszymi literami. Ponieważ redukcja nie ma wartości początkowej, rozpocznie wielkie litery, zaczynając od drugiego słowa.

Jeśli chcesz PascalCase, po prostu dodaj początkowy pusty ciąg ,'')do metody redukującej.

Marcina Szyska
źródło
3

podążając za czytelnym podejściem @ Scotta, trochę dopracowania

// przekonwertuj dowolny ciąg na camelCase
var toCamelCase = function (str) {
  return str.toLowerCase ()
    .replace (/ ['"] / g,' ')
    .replace (/ \ W + / g, '')
    .replace (/ (.) / g, function ($ 1) {return $ 1.toUpperCase ();})
    .replace (/ / g, '');
}
cc młody
źródło
3

trochę zmodyfikowana odpowiedź Scotta:

toCamelCase = (string) ->
  string
    .replace /[\s|_|-](.)/g, ($1) -> $1.toUpperCase()
    .replace /[\s|_|-]/g, ''
    .replace /^(.)/, ($1) -> $1.toLowerCase()

teraz zastępuje również „-” i „_”.

historia słoneczna
źródło
3

Wszystkie 14 permutacji poniżej daje ten sam wynik „equipmentClassName”.

String.prototype.toCamelCase = function() {
  return this.replace(/[^a-z ]/ig, '')  // Replace everything but letters and spaces.
    .replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, // Find non-words, uppercase letters, leading-word letters, and multiple spaces.
      function(match, index) {
        return +match === 0 ? "" : match[index === 0 ? 'toLowerCase' : 'toUpperCase']();
      });
}

String.toCamelCase = function(str) {
  return str.toCamelCase();
}

var testCases = [
  "equipment class name",
  "equipment class Name",
  "equipment Class name",
  "equipment Class Name",
  "Equipment class name",
  "Equipment class Name",
  "Equipment Class name",
  "Equipment Class Name",
  "equipment className",
  "equipment ClassName",
  "Equipment ClassName",
  "equipmentClass name",
  "equipmentClass Name",
  "EquipmentClass Name"
];

for (var i = 0; i < testCases.length; i++) {
  console.log(testCases[i].toCamelCase());
};

Panie Polywhirl
źródło
Tak. Wolę używać metod prototypowych z łańcuchami znaków niż funkcjami. Pomaga w łańcuchach.
russellmania
3

możesz skorzystać z tego rozwiązania:

String.prototype.toCamelCase = function(){
  return this.replace(/\s(\w)/ig, function(all, letter){return letter.toUpperCase();})
             .replace(/(^\w)/, function($1){return $1.toLowerCase()});
};

console.log('Equipment className'.toCamelCase());

Chang Hoon Lee
źródło
Ten przykład pokazuje, jak używać dwóch innych funkcji w metodzie zamiany.
Chang Hoon Lee
3

Ponieważ to pytanie wymagało jeszcze jednej odpowiedzi ...

Wypróbowałem kilka poprzednich rozwiązań i wszystkie miały tę czy inną wadę. Niektórzy nie usunęli interpunkcji; niektórzy nie zajmowali się sprawami z liczbami; niektóre nie obsługiwały wielu znaków interpunkcyjnych z rzędu.

Żaden z nich nie radził sobie ze sznurkiem jak a1 2b. Nie ma wyraźnie zdefiniowanej konwencji dla tego przypadku, ale niektóre inne pytania dotyczące przepełnienia stosu sugerowały oddzielenie liczb za pomocą podkreślenia.

Wątpię, czy jest to najbardziej wydajna odpowiedź (trzy wyrażenia regularne przechodzą przez ciąg zamiast jednego lub dwóch), ale przechodzi wszystkie testy, jakie przychodzą mi do głowy. Szczerze mówiąc, naprawdę nie mogę sobie wyobrazić przypadku, w którym robisz tyle konwersji na wielbłądzie, że wydajność miałaby znaczenie.

(Dodałem to jako pakiet npm . Zawiera również opcjonalny parametr boolean, aby zwrócić Pascal Case zamiast Camel Case.)

const underscoreRegex = /(?:[^\w\s]|_)+/g,
    sandwichNumberRegex = /(\d)\s+(?=\d)/g,
    camelCaseRegex = /(?:^\s*\w|\b\w|\W+)/g;

String.prototype.toCamelCase = function() {
    if (/^\s*_[\s_]*$/g.test(this)) {
        return '_';
    }

    return this.replace(underscoreRegex, ' ')
        .replace(sandwichNumberRegex, '$1_')
        .replace(camelCaseRegex, function(match, index) {
            if (/^\W+$/.test(match)) {
                return '';
            }

            return index == 0 ? match.trimLeft().toLowerCase() : match.toUpperCase();
        });
}

Przypadki testowe (Jest)

test('Basic strings', () => {
    expect(''.toCamelCase()).toBe('');
    expect('A B C'.toCamelCase()).toBe('aBC');
    expect('aB c'.toCamelCase()).toBe('aBC');
    expect('abc      def'.toCamelCase()).toBe('abcDef');
    expect('abc__ _ _def'.toCamelCase()).toBe('abcDef');
    expect('abc__ _ d_ e _ _fg'.toCamelCase()).toBe('abcDEFg');
});

test('Basic strings with punctuation', () => {
    expect(`a'b--d -- f.h`.toCamelCase()).toBe('aBDFH');
    expect(`...a...def`.toCamelCase()).toBe('aDef');
});

test('Strings with numbers', () => {
    expect('12 3 4 5'.toCamelCase()).toBe('12_3_4_5');
    expect('12 3 abc'.toCamelCase()).toBe('12_3Abc');
    expect('ab2c'.toCamelCase()).toBe('ab2c');
    expect('1abc'.toCamelCase()).toBe('1abc');
    expect('1Abc'.toCamelCase()).toBe('1Abc');
    expect('abc 2def'.toCamelCase()).toBe('abc2def');
    expect('abc-2def'.toCamelCase()).toBe('abc2def');
    expect('abc_2def'.toCamelCase()).toBe('abc2def');
    expect('abc1_2def'.toCamelCase()).toBe('abc1_2def');
    expect('abc1 2def'.toCamelCase()).toBe('abc1_2def');
    expect('abc1 2   3def'.toCamelCase()).toBe('abc1_2_3def');
});

test('Oddball cases', () => {
    expect('_'.toCamelCase()).toBe('_');
    expect('__'.toCamelCase()).toBe('_');
    expect('_ _'.toCamelCase()).toBe('_');
    expect('\t_ _\n'.toCamelCase()).toBe('_');
    expect('_a_'.toCamelCase()).toBe('a');
    expect('\''.toCamelCase()).toBe('');
    expect(`\tab\tcd`.toCamelCase()).toBe('abCd');
    expect(`
ab\tcd\r

-_

|'ef`.toCamelCase()).toBe(`abCdEf`);
});
dx_over_dt
źródło
Świetna robota, dziękuję. Obsługuje znacznie więcej scenariuszy w porównaniu z innymi podstawowymi odpowiedziami.
sean2078
2

Oto moje rozwiązanie:

const toCamelWord = (word, idx) =>
  idx === 0 ?
  word.toLowerCase() :
  word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();

const toCamelCase = text =>
  text
  .split(/[_-\s]+/)
  .map(toCamelWord)
  .join("");

console.log(toCamelCase('User ID'))

Daniil Khudiakov
źródło
1

Ta metoda wydaje się być lepsza od większości odpowiedzi tutaj, jest jednak trochę zepsuta, bez zastępowania, bez wyrażenia regularnego, po prostu tworzy nowy ciąg, który jest camelCase.

String.prototype.camelCase = function(){
    var newString = '';
    var lastEditedIndex;
    for (var i = 0; i < this.length; i++){
        if(this[i] == ' ' || this[i] == '-' || this[i] == '_'){
            newString += this[i+1].toUpperCase();
            lastEditedIndex = i+1;
        }
        else if(lastEditedIndex !== i) newString += this[i].toLowerCase();
    }
    return newString;
}
Thieu
źródło
1

Opiera się to na odpowiedzi przekazanej przez CMS, usuwając wszelkie znaki niealfabetyczne, w tym podkreślenia, co \wnie powoduje usunięcia.

function toLowerCamelCase(str) {
    return str.replace(/[^A-Za-z0-9]/g, ' ').replace(/^\w|[A-Z]|\b\w|\s+/g, function (match, index) {
        if (+match === 0 || match === '-' || match === '.' ) {
            return ""; // or if (/\s+/.test(match)) for white spaces
        }
        return index === 0 ? match.toLowerCase() : match.toUpperCase();
    });
}

toLowerCamelCase("EquipmentClass name");
toLowerCamelCase("Equipment className");
toLowerCamelCase("equipment class name");
toLowerCamelCase("Equipment Class Name");
toLowerCamelCase("Equipment-Class-Name");
toLowerCamelCase("Equipment_Class_Name");
toLowerCamelCase("Equipment.Class.Name");
toLowerCamelCase("Equipment/Class/Name");
// All output e
kołodziej
źródło
1

Wielkie litery wielbłąda („TestString”) do małych liter wielbłąda („testString”) bez użycia wyrażenia regularnego (spójrzmy prawdzie w oczy, wyrażenie regularne jest złe):

'TestString'.split('').reduce((t, v, k) => t + (k === 0 ? v.toLowerCase() : v), '');
Christoph Bühler
źródło
2
Parametry pojedynczego znaku są nadal nieco złe pod względem czytelności
danwellman
1

Skończyło się na stworzeniu nieco bardziej agresywnego rozwiązania:

function toCamelCase(str) {
  const [first, ...acc] = str.replace(/[^\w\d]/g, ' ').split(/\s+/);
  return first.toLowerCase() + acc.map(x => x.charAt(0).toUpperCase() 
    + x.slice(1).toLowerCase()).join('');
}

Ten, powyżej, usunie wszystkie znaki niealfanumeryczne i małe litery słów, które w przeciwnym razie pozostałyby wielkimi literami, np.

  • Size (comparative) => sizeComparative
  • GDP (official exchange rate) => gdpOfficialExchangeRate
  • hello => hello
bjornl
źródło
1
function convertStringToCamelCase(str){
    return str.split(' ').map(function(item, index){
        return index !== 0 
            ? item.charAt(0).toUpperCase() + item.substr(1) 
            : item.charAt(0).toLowerCase() + item.substr(1);
    }).join('');
}      
user6921695
źródło
1

Oto moja sugestia:

function toCamelCase(string) {
  return `${string}`
    .replace(new RegExp(/[-_]+/, 'g'), ' ')
    .replace(new RegExp(/[^\w\s]/, 'g'), '')
    .replace(
      new RegExp(/\s+(.)(\w+)/, 'g'),
      ($1, $2, $3) => `${$2.toUpperCase() + $3.toLowerCase()}`
    )
    .replace(new RegExp(/\s/, 'g'), '')
    .replace(new RegExp(/\w/), s => s.toLowerCase());
}

lub

String.prototype.toCamelCase = function() {
  return this
    .replace(new RegExp(/[-_]+/, 'g'), ' ')
    .replace(new RegExp(/[^\w\s]/, 'g'), '')
    .replace(
      new RegExp(/\s+(.)(\w+)/, 'g'),
      ($1, $2, $3) => `${$2.toUpperCase() + $3.toLowerCase()}`
    )
    .replace(new RegExp(/\s/, 'g'), '')
    .replace(new RegExp(/\w/), s => s.toLowerCase());
};

Przypadki testowe:

describe('String to camel case', function() {
  it('should return a camel cased string', function() {
    chai.assert.equal(toCamelCase('foo bar'), 'fooBar');
    chai.assert.equal(toCamelCase('Foo Bar'), 'fooBar');
    chai.assert.equal(toCamelCase('fooBar'), 'fooBar');
    chai.assert.equal(toCamelCase('FooBar'), 'fooBar');
    chai.assert.equal(toCamelCase('--foo-bar--'), 'fooBar');
    chai.assert.equal(toCamelCase('__FOO_BAR__'), 'fooBar');
    chai.assert.equal(toCamelCase('!--foo-¿?-bar--121-**%'), 'fooBar121');
  });
});
kalicki2k
źródło
1

Wiem, że to stara odpowiedź, ale obsługuje zarówno białe znaki, jak i _ (lodash)

function toCamelCase(s){
    return s
          .replace(/_/g, " ")
          .replace(/\s(.)/g, function($1) { return $1.toUpperCase(); })
          .replace(/\s/g, '')
          .replace(/^(.)/, function($1) { return $1.toLowerCase(); });
}

console.log(toCamelCase("Hello world");
console.log(toCamelCase("Hello_world");

// Both print "helloWorld"
Sampgun
źródło
Dzięki za to, ale nie wydaje się być zabłąkany "w .replace(/_/g", " ")że błędy przyczyny kompilacji?
Crashalot
1
const toCamelCase = str =>
  str
    .replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase())
    .replace(/^\w/, c => c.toLowerCase());
Gaurav Mogha
źródło
0

EDYCJA : Teraz działa w IE8 bez zmian.

EDYCJA : Byłem w mniejszości, jeśli chodzi o to, czym właściwie jest camelCase (wiodące małe litery vs. wielkie). Społeczność uważa, że ​​wiodącą małą literą jest wielbłąd, a wiodącą wielką literą jest paskal. Stworzyłem dwie funkcje, które używają tylko wzorców regex. :) Używamy więc ujednoliconego słownictwa. Zmieniłem swoje stanowisko, aby dopasować się do większości.


Uważam, że potrzebujesz tylko jednego wyrażenia regularnego w obu przypadkach:

var camel = " THIS is camel case "
camel = $.trim(camel)
    .replace(/[^A-Za-z]/g,' ') /* clean up non-letter characters */
    .replace(/(.)/g, function(a, l) { return l.toLowerCase(); })
    .replace(/(\s.)/g, function(a, l) { return l.toUpperCase(); })
    .replace(/[^A-Za-z\u00C0-\u00ff]/g,'');
// Returns "thisIsCamelCase"

lub

var pascal = " this IS pascal case "
pascal = $.trim(pascal)
  .replace(/[^A-Za-z]/g,' ') /* clean up non-letter characters */
  .replace(/(.)/g, function(a, l) { return l.toLowerCase(); })
  .replace(/(^.|\s.)/g, function(a, l) { return l.toUpperCase(); })
  .replace(/[^A-Za-z\u00C0-\u00ff]/g,'');
// Returns "ThisIsPascalCase"

W funkcjach: Zauważysz, że w tych funkcjach zamiana polega na zamianie dowolnego znaku innego niż az spacją na pusty ciąg. Ma to na celu utworzenie granic słów dla wielkich liter. „hello-MY # world” -> „HelloMyWorld”

// remove \u00C0-\u00ff] if you do not want the extended letters like é
function toCamelCase(str) {
    var retVal = '';

    retVal = $.trim(str)
      .replace(/[^A-Za-z]/g, ' ') /* clean up non-letter characters */
      .replace(/(.)/g, function (a, l) { return l.toLowerCase(); })
      .replace(/(\s.)/g, function (a, l) { return l.toUpperCase(); })
      .replace(/[^A-Za-z\u00C0-\u00ff]/g, '');

    return retVal
}

function toPascalCase(str) {
    var retVal = '';

    retVal = $.trim(str)
      .replace(/[^A-Za-z]/g, ' ') /* clean up non-letter characters */
      .replace(/(.)/g, function (a, l) { return l.toLowerCase(); })
      .replace(/(^.|\s.)/g, function (a, l) { return l.toUpperCase(); })
      .replace(/[^A-Za-z\u00C0-\u00ff]/g, '');

    return retVal
}

Uwagi:

  • Zostawiłem A-Za-z vs dodanie flagi niewrażliwości na wielkość liter (i) do wzorca (/ [^ AZ] / ig) dla czytelności.
  • Działa to w IE8 (srsly, który już używa IE8). Używając narzędzi dev (F12), które testowałem w IE11, IE10, IE9, IE8, IE7 i IE5. Działa we wszystkich trybach dokumentów.
  • W ten sposób pierwsza litera łańcuchów będzie zaczynać się od białych znaków lub bez nich.

Cieszyć się

Joe Johnston
źródło
Pierwsza litera jest nadal wielka?
Dave Clarke
Tak. W przypadku, gdy na początku jest on niższy lub wyższy, zostanie zapisany wielką literą.
Joe Johnston
2
Cóż, to nie jest przypadek wielbłąda - i nie pasuje do tego, o co prosił OP?
Dave Clarke
Miejmy nadzieję, że ta zmiana zapewni wyniki, których szukał OP. Przez całe życie nie miałem pojęcia, po co ten głos przeciw. Nie odpowiadam na OP ... To wystarczy. :)
Joe Johnston
1
Uważam, że „PascalCase” jest tym, co nazywamy camelCase z wiodącym kapitałem.
Ted Morin
0

Myślę, że to powinno działać ..

function cammelCase(str){
    let arr = str.split(' ');
    let words = arr.filter(v=>v!='');
    words.forEach((w, i)=>{
        words[i] = w.replace(/\w\S*/g, function(txt){
            return txt.charAt(0).toUpperCase() + txt.substr(1);
        });
    });
    return words.join('');
}
Darryl Ceguerra
źródło
0

Nie używaj String.prototype.toCamelCase (), ponieważ String.prototypes są tylko do odczytu, większość kompilatorów js wyświetli to ostrzeżenie.

Podobnie jak ja, ci, którzy wiedzą, że ciąg zawsze będzie zawierał tylko jedną spację, mogą zastosować prostsze podejście:

let name = 'test string';

let pieces = name.split(' ');

pieces = pieces.map((word, index) => word.charAt(0)[index===0 ? 'toLowerCase' :'toUpperCase']() + word.toLowerCase().slice(1));

return pieces.join('');

Miłego dnia. :)

Jaskaran Singh
źródło