Convertir camelCaseText en texto de caso de oración

144

¿Cómo puedo convertir una cadena como 'helloThere' o 'HelloThere' a 'Hello There' en JavaScript?

HyderA
fuente
9
hmm .. ¿Cuál es su salida esperada para iLiveInTheUSA?
wim
8
Yo vivo en la U ... ¡Oh, mierda! - Pero en mi caso, tengo un conjunto limitado de cadenas y no existen cadenas que puedan romper un convertidor simple. Buena captura sin embargo!
HyderA
Del mismo modo, uSBPort debería generar un "Puerto USB"
signonsridhar
2
@wim: iLiveInTheUSA debería ser iLiveInTheUsa en la notación correcta de caso de camello, pero eso presentaría diferentes problemas.
Konrad Höffner

Respuestas:

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

escribe con mayúscula la primera letra, como ejemplo.

Tenga en cuenta el espacio en " $1".

EDITAR: se agregó un ejemplo de capitalización de la primera letra. Por supuesto, en caso de que la primera letra ya sea mayúscula, tendría un espacio libre para eliminar.

Maestro Zen
fuente
1
Excavo el uso de espacios text.replace, he estado rellenando llamadas de función con más de 2 argumentos con espacios para
facilitar la
8
uSBPorts => Puertos USB, no es lo que esperaba, quiero un puerto USB
signonsridhar
¿Qué tal escribir Non-GoogleChrome?
tim
107

Alternativamente usando lodash :

lodash.startCase(str);

Ejemplo:

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

Lodash es una buena biblioteca para dar acceso directo a muchas tareas js cotidianas. Hay muchas otras funciones similares de manipulación de cadenas como camelCase, kebabCaseetc.

Wtower
fuente
Si lo intenta hello world, la salida debería ser Hello There, en este caso, loadash no será útil.
Abhishek Kumar
@AbhishekKumar startCase of lodash se convertirá hello worlden Hello World lodash.com/docs/4.17.15#upperFirst
usuario1696017
Tienes razón hermano. Por error he escrito hello therea hello world.
Abhishek Kumar
2
Cada vez que pienso "no hay forma de que lodash haga esto también", lo hace.
desde el
Tenga cuidado a partir de la v4, esta función elimina caracteres especiales como ä y los convierte en caracteres ASCII (a en este caso)
collerek
52

Tuve un problema similar y lo solucioné así:

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

Para una solución más robusta:

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

http://jsfiddle.net/PeYYQ/

Entrada:

 helloThere 
 HelloThere 
 ILoveTheUSA
 iLoveTheUSA

Salida:

 hello There 
 Hello There 
 I Love The USA
 i Love The USA
James Khoury
fuente
pone un espacio extra en el inicio
hannad rehman
44
No es un caso de oración como OP preguntó. La primera letra debe estar en mayúscula.
H Dog
Además, agrega un espacio adicional entre palabras
Alacritas,
34

Ejemplo sin efectos secundarios.

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();
    });
}

En ES6

const camel2title = (camelCase) => camelCase
  .replace(/([A-Z])/g, (match) => ` ${match}`)
  .replace(/^./, (match) => match.toUpperCase());
renevanderark
fuente
1
Sólido, +1 para el fragmento es6.
BradStell
44
Para su información, esto agrega espacios en blanco adicionales al comienzo de la oración.
Dale Zak
20

La mejor cadena que he encontrado para probar las funciones de camello-caso-título-caso es este ejemplo ridículamente absurdo, que prueba muchos casos extremos. Que yo sepa, ninguna de las funciones publicadas anteriormente maneja esto correctamente :

ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D

Esto debe convertirse a:

Para obtener su GED a tiempo Una canción sobre los 26 ABC es esencial, pero una tarjeta de identificación personal para el usuario 456 en la habitación 26A que contiene ABC 26 veces no es tan fácil como 123 para C3PO o R2D2 o 2R2D

Si solo desea una función simple que maneje casos como el anterior (y más casos que muchas de las respuestas anteriores), aquí está la que escribí. Este código no es particularmente elegante o rápido, pero es simple, comprensible y funciona.

Un ejemplo ejecutable en línea está en jsfiddle , o puede ver el resultado del fragmento a continuación en su consola:

// 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)));

Chris Kline
fuente
11

Basado en uno de los ejemplos anteriores, se me ocurrió esto:

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

Funciona para mí porque utiliza .trim()para manejar el caso de borde donde la primera letra está en mayúscula y terminas con un espacio inicial adicional.

Referencia: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim

Anthony S.
fuente
10

Ok, llegué unos años tarde al juego, pero tenía una pregunta similar y quería hacer una solución de reemplazo único para cada entrada posible. Debo dar la mayor parte del crédito a @ZenMaster en este hilo y @Benjamin Udink ten Cate en este hilo. Aquí está el código:

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);
}

Tiene tres cláusulas, todas con anticipación para evitar que el motor de expresiones regulares consuma demasiados caracteres:

  1. [A-Z](?=[A-Z][a-z])busca una letra mayúscula seguida de una letra mayúscula y luego minúscula. Esto es para acabar con acrónimos como Estados Unidos.
  2. [^A-Z](?=[A-Z])busca una letra no mayúscula seguida de una letra mayúscula. Esto termina palabras como myWord y símbolos como 99Bottles.
  3. [a-zA-Z](?=[^a-zA-Z])busca una letra seguida de una no letra. Esto termina palabras antes de símbolos como BFG9000.

Esta pregunta estaba en la parte superior de mis resultados de búsqueda, ¡así que espero poder salvar a otros algún tiempo!

Christopher Smith
fuente
9

Aquí está mi versión de la misma. Agrega un espacio antes de cada letra en inglés de UpperCase que viene después de una letra minúscula en inglés y también escribe en mayúscula la primera letra si es necesario:

Por ejemplo:
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;
  }
asafd
fuente
6

Esta implementación toma en consideración letras mayúsculas y números consecutivos.

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));
});

Rendimiento esperado:

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
Dipu
fuente
Usaría la respuesta de Chris Kline que se adapta a cadenas como "Dirección IP" (donde esta función la convierte en "Dirección IP"
John Hamm
@ JohnHamm Su entrada es "Dirección IP", ¿verdad? ¡No es un caso de camellos! Lea sobre el caso de camello aquí: en.wikipedia.org/wiki/Camel_case No coloque espacio entre e ingrese "IPAddress" solamente. Esta función funciona bien.
Dipu
3

Puede usar una función como esta:

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"

Código con un montón de cadenas de prueba aquí: http://jsfiddle.net/jfriend00/FWLuV/ .

Versión alternativa que mantiene los espacios principales aquí: http://jsfiddle.net/jfriend00/Uy2ac/ .

jfriend00
fuente
Sé que no era un requisito en la pregunta, pero su solución no funciona " helloWorld", por ejemplo.
ZenMaster
Sí, ese es un nuevo requisito. Traté de hacer exactamente lo que originalmente pediste. De todos modos, la forma abreviada es fácil de eliminar espacios iniciales si no los necesita allí de todos modos. Si quisieras dejarlos en su lugar, eso también se podría hacer.
jfriend00
Aquí hay un jsFiddle que muestra un método que funciona con el nuevo requerimiento de "helloWorld" y mantiene el espacio inicial (si lo desea): jsfiddle.net/jfriend00/Uy2ac .
jfriend00
Agradable. Sin embargo, me pregunto el rendimiento de la misma. La función del controlador se llamará en cada partido, ¿no?
ZenMaster
Si está haciendo un montón de estos en un entorno sensible al rendimiento, tomaría algunas pruebas jsperf en un montón de navegadores para ver cuál sería la solución más rápida. Llamar una devolución de llamada no es gran cosa. Las expresiones regulares, de cualquier tipo, rara vez son la solución más rápida frente al código de propósito especial, pero guardan mucho código (y a menudo algunos errores), por lo que a menudo son la opción deseada. Depende de tus requerimientos.
jfriend00
3

prueba esta biblioteca

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"
Barno
fuente
2

Ninguna de las respuestas anteriores funcionó perfectamente para mí, por lo que tuve que venir con mi propia bicicleta:

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');
}

Casos de prueba:

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

Esto funciona para mí, mira esto

CamelcaseToWord ("MiNombre"); // devuelve Mi nombre

    function CamelcaseToWord(string){
      return string.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1");
    }
Poorna Rao
fuente
1
Bienvenido a SO :) Agregue al menos una línea explicativa a su código. También asegúrese de que sea su trabajo intelectual o cite las fuentes.
Lorenz Lo Sauer
Debe eliminar el espacio en un lat "$ 1". string.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, "$1");
Valeria Shpiner
2

Creo que esto se puede hacer solo con el registro exp /([a-z]|[A-Z]+)([A-Z])/gy el reemplazo "$1 $2".

ILoveTheUSADope -> I Love The USA Dope

Miguel Enrique León Figueras
fuente
No exactamente, para la cadena QWERTYdevuelve QWERT Y.
itachi
2

Si se ocupa de Capital Camel Case, este fragmento puede ayudarlo, también contiene algunas especificaciones para que pueda estar seguro de que coincide con su caso.

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

Y especificaciones:

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')
 })
})
Purkhalo Alex
fuente
1

No probé la respuesta de todos, pero las pocas soluciones con las que jugué no cumplían con todos mis requisitos.

Pude llegar a algo que hizo ...

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(), 
              '')
Tabbyofjudah
fuente
1

A continuación se muestra un enlace que muestra la cadena de casos de camello a la cadena de oración utilizando expresiones regulares.

Entrada

myCamelCaseSTRINGToSPLITDemo

Salida

my Camel Case STRING To SPLIT Demo


Esta es la expresión regular para la conversión del caso de camello a texto de oración

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

con $1 $2como substituto.

Haga clic para ver la conversión en expresiones regulares

Rahul
fuente
Proporcione el contenido relevante de su enlace en el cuerpo de su respuesta.
Grant Miller
1

Entrada javaScript

Salida de 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");
Manas
fuente
1

Una solución más basada en RegEx.

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

Explicación

El RegEx anterior consta de dos partes similares separadas por el operador OR . La primera mitad:

  1. ([A-Z]) - coincide con letras mayúsculas ...
  2. (?=[A-Z][a-z]) - seguido de una secuencia de letras mayúsculas y minúsculas.

Cuando se aplica a la secuencia FOo , esto efectivamente coincide con su letra F.

O el segundo escenario:

  1. ([a-z]) - coincide con letras minúsculas ...
  2. (?=[A-Z]) - seguido de una letra mayúscula.

Cuando se aplica a la secuencia barFoo , esto efectivamente coincide con su letra r .

Cuando se encuentran todos los candidatos de reemplazo, lo último que debe hacer es reemplazarlos con la misma letra pero con un carácter de espacio adicional. Para esto podemos usarlo '$& 'como reemplazo, y se resolverá en una subcadena coincidente seguida de un carácter de espacio.

Ejemplo

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"]
itachi
fuente
-1

Agregué otra solución ES6 que me gustó más después de no estar contento con algunos de los pensamientos anteriores.

https://codepen.io/902Labs/pen/mxdxRv?editors=0010#0

const camelize = (str) => str
    .split(' ')
    .map(([first, ...theRest]) => (
        `${first.toUpperCase()}${theRest.join('').toLowerCase()}`)
    )
    .join(' ');
usuario169251
fuente