Convert different strings to snake_case in Javascript - javascript

I know that we have a question similar to this but not quite the same.
I'm trying to make my function work which takes in a string as an argument and converts it to snake_case . It works most of the time with all the fancy !?<>= characters but there is one case that it can't convert and its camelCase .
It fails when I'm passing strings like snakeCase. It returns snakecase instead of snake_case.
I tried to implement it but I ended up just messing it up even more..
Can I have some help please?
my code:
const snakeCase = string => {
string = string.replace(/\W+/g, " ").toLowerCase().split(' ').join('_');
if (string.charAt(string.length - 1) === '_') {
return string.substring(0, string.length - 1);
}
return string;
}

You need to be able to detect the points at which an upper-case letter is in the string following another letter (that is, not following a space). You can do this with a regular expression, before you call toLowerCase on the input string:
\B(?=[A-Z])
In other words, a non-word boundary, followed by an upper case character. Split on either the above, or on a literal space, then .map the resulting array to lower case, and then you can join by underscores:
const snakeCase = string => {
return string.replace(/\W+/g, " ")
.split(/ |\B(?=[A-Z])/)
.map(word => word.toLowerCase())
.join('_');
};
console.log(snakeCase('snakeCase'));

Let's try that again Stan... this should do snake_case while realising that CamelCASECapitals = camel_case_capitals. It's basically the accepted answer with a pre-filter.
let splitCaps = string => string
.replace(/([a-z])([A-Z]+)/g, (m, s1, s2) => s1 + ' ' + s2)
.replace(/([A-Z])([A-Z]+)([^a-zA-Z0-9]*)$/, (m, s1, s2, s3) => s1 + s2.toLowerCase() + s3)
.replace(/([A-Z]+)([A-Z][a-z])/g,
(m, s1, s2) => s1.toLowerCase() + ' ' + s2);
let snakeCase = string =>
splitCaps(string)
.replace(/\W+/g, " ")
.split(/ |\B(?=[A-Z])/)
.map(word => word.toLowerCase())
.join('_');
> a = ['CamelCASERules', 'IndexID', 'CamelCASE', 'aID',
'theIDForUSGovAndDOD', 'TheID_', '_IDOne']
> _.map(a, snakeCase)
['camel_case_rules', 'index_id', 'camel_case', 'a_id', 'the_id_for_us_gov_and_dod',
'the_id_', '_id_one']
// And for the curious, here's the output from the pre-filter:
> _.map(a, splitCaps)
['Camel case Rules', 'Index Id', 'Camel Case', 'a Id', 'the id For us Gov And Dod',
'The Id_', '_id One']

Suppose the string is Hello World? and you want the returned value as hello_world? (with the character, then follow the below code)
const snakeCase = (string) => {
return string.replace(/\d+/g, ' ')
.split(/ |\B(?=[A-Z])/)
.map((word) => word.toLowerCase())
.join('_');
};
Example
snakeCase('Hello World?')
// "hello_world?"
snakeCase('Hello & World')
// "hello_&_world"

EDIT: It turns out this answer isn’t fool proof. The fool, being me ;-) Please check out a better one by Orwellophile here: https://stackoverflow.com/a/69878219/5377276
——
I think this one should cover all the bases 😄
It was inspired by #h0r53's answer to the accepted answer. However it evolved into a more complete function, as it will convert any string, camelCase, kebab-case or otherwise into snake_case the way you'd expect it, containing only a-z and 0-9 characters, usable for function and variable names:
convert_to_snake_case(string) {
return string.charAt(0).toLowerCase() + string.slice(1) // lowercase the first character
.replace(/\W+/g, " ") // Remove all excess white space and replace & , . etc.
.replace(/([a-z])([A-Z])([a-z])/g, "$1 $2$3") // Put a space at the position of a camelCase -> camel Case
.split(/\B(?=[A-Z]{2,})/) // Now split the multi-uppercases customerID -> customer,ID
.join(' ') // And join back with spaces.
.split(' ') // Split all the spaces again, this time we're fully converted
.join('_') // And finally snake_case things up
.toLowerCase() // With a nice lower case
}
Conversion examples:
'snakeCase' => 'snake_case'
'CustomerID' => 'customer_id'
'GPS' => 'gps'
'IP-address' => 'ip_address'
'Another & Another, one too' => 'another_another_one_too'
'random ----- Thing123' => 'random_thing123'
'kebab-case-example' => 'kebab_case_example'

There is method in lodash named snakeCase(). You can consider that as well.
https://lodash.com/docs/4.17.15#snakeCase

Orwellophile's answer does not work for uppercase words delimited by a space:
E.g: 'TEST CASE' => t_e_s_t_case
The following solution does not break consecutive upper case characters and is a little shorter:
const snakeCase = str =>
str &&
str
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.map(x => x.toLowerCase())
.join('_');
However, trailing underscores after uppercase words (examples from Orwellophile as well), do not work properly.
E.g: 'TheID_' => the_i_d
Taken from https://www.w3resource.com/javascript-exercises/fundamental/javascript-fundamental-exercise-120.php.

Related

Replace every character but which is in my regex

I found this regex which validates Instagram usernames
/^(?!.*\.\.)(?!.*\.$)[^\W][\w.]{0,29}$/gim
What I'm trying to do is to replace all characters which not match my regex
let regex = new RegExp(/^(?!.*\.\.)(?!.*\.$)[^\W][\w.]{0,29}$/gim);
const filteredString = replace(text, regex, '');
I tried to add ?! at the start as a negative lookahead but no luck
Removing all the aprts that don't mach is the same as keeping the matches.
Instead of using replace you can use match and add all the matches to your filteredString, like shown below:
let text = `riegiejeyaranchen
riegie.jeyaranchen
_riegie.jeyaranchen
.riegie
riegie..jeyaranchen
riegie._.jeyaranchen
riegie.
riegie.__`;
let regex = new RegExp(/^(?!.*\.\.)(?!.*\.$)[^\W][\w.]{0,29}$/gim);
let filteredString = '';
text.match(regex).forEach(value =>
{
filteredString += value + '\r\n';
});
console.log(filteredString);
Of course the \r\n is optional (just places one on each line).
Now you get a string where non matches are removed.
Based on the regex /^(?!.*\.\.)(?!.*\.$)[^\W][\w.]{0,29}$/, the name must not have consecutive dots, no leading and trailing dots, and have max 30 word/dot chars. This code cleans up names accordingly:
[
'f',
'foobar',
'_foo.bar',
'_foo..bar',
'_foo...bar',
'_foo.bar.',
'.foo.bar',
'foo<$^*>bar',
'123456789012345678901234567890',
'1234567890123456789012345678901'
].forEach(name => {
let clean = name
.replace(/\.{2,}/g, '.') // reduce multiple dots to one dot
.replace(/^\.+/, '') // remove leading dots
.replace(/\.+$/, '') // remove trailing dots
.replace(/[^\w\.]/g, '') // remove non word/dot chars
.replace(/^(.{30}).+/, '$1'); // restrict to 30 chars
console.log(name + ' => ' + clean);
});
Output:
f => f
foobar => foobar
_foo.bar => _foo.bar
_foo..bar => _foo.bar
_foo...bar => _foo.bar
_foo.bar. => _foo.bar
.foo.bar => foo.bar
foo<$^*>bar => foobar
123456789012345678901234567890 => 123456789012345678901234567890
1234567890123456789012345678901 => 123456789012345678901234567890
Note that the original regex requires at least one char. You need to test for empty string after cleanup.

convert combination of replace methods onto one

I have a combination of replace methods. How can I convert them to one:
.replace(/\s+/g, " ").replace(/\,|\?|\!|\:|\./g,'').replace("'", "_")
Is there any solution?
It's possible with a replacer function which alternates between the different possibilities, captures the matching subpattern, and checks which subpattern was matched in the replacer function, but it's really ugly. Your current solution is much easier to read.
const string = ' here is multiple spaces consolidated, punctuation removed!! and apostrophes don\'t exist! ';
const result = string
.replace(
/(\s+)|(\,|\?|\!|\:|\.)|(')/g,
(match, g1, g2, g3) => (
g1 ? ' ' :
g2 ? '' :
'_'
)
);
console.log(result);
I'd use your original version with a slight tweak: use a character set in the second replace instead, it'll be easier to read.
const string = ' here is multiple spaces consolidated, punctuation removed!! and apostrophes don\'t exist! ';
const result = string
.replace(/\s+/g, " ")
.replace(/[,?!:.]/g,'')
.replace("'", "_");
console.log(result);

Lodash title case (uppercase first letter of every word)

I'm looking through the lodash docs and other Stack Overflow questions - while there are several native JavaScript ways of accomplishing this task, is there a way I can convert a string to title case using purely lodash functions (or at least existing prototypal functions) so that I don't have to use a regular expression or define a new function?
e.g.
This string ShouLD be ALL in title CASe
should become
This String Should Be All In Title Case
This can be done with a small modification of startCase:
_.startCase(_.toLower(str));
console.log(_.startCase(_.toLower("This string ShouLD be ALL in title CASe")));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
_.startCase(_.camelCase(str))
For non-user-generated text, this handles more cases than the accepted answer
> startCase(camelCase('myString'))
'My String'
> startCase(camelCase('my_string'))
'My String'
> startCase(camelCase('MY_STRING'))
'My String'
> startCase(camelCase('my string'))
'My String'
> startCase(camelCase('My string'))
'My String'
with lodash version 4.
_.upperFirst(_.toLower(str))
'This string ShouLD be ALL in title CASe'
.split(' ')
.map(_.capitalize)
.join(' ');
There are mixed answers to this question.
Some are recommending using _.upperFirst while some recommending _.startCase.
Know the difference between them.
i) _.upperFirst will transform the first letter of your string, then string might be of a single word or multiple words but the only first letter of your string is transformed to uppercase.
_.upperFirst('jon doe')
output:
Jon doe
check the documentation https://lodash.com/docs/4.17.10#upperFirst
ii) _.startCase will transform the first letter of every word inside your string.
_.startCase('jon doe')
output:
Jon Doe
https://lodash.com/docs/4.17.10#startCase
That's the cleanest & most flexible implementation imo from testing it on my own use cases.
import { capitalize, map } from "lodash";
const titleCase = (str) => map(str.split(" "), capitalize).join(" ");
// titleCase("ALFRED NÚÑEZ") => "Alfred Núñez"
// titleCase("alfred núñez") => "Alfred Núñez"
// titleCase("AlFReD nÚñEZ") => "Alfred Núñez"
// titleCase("-") => "-"
From https://github.com/lodash/lodash/issues/3383#issuecomment-430586750
'JHON&JOHN C/O DR. BLah'.replace(/\w+/g, _.capitalize);
result:
'Jhon&John C/O Dr. Blah'
Here's a way using ONLY lodash methods and no builtin methods:
_.reduce(_.map(_.split("Hello everyOne IN the WOrld", " "), _.capitalize), (a, b) => a + " " + b)
This can be done with only lodash
properCase = string =>
words(string)
.map(capitalize)
.join(' ');
const proper = properCase('make this sentence propercase');
console.log(proper);
//would return 'Make This Sentence Propercase'
var s = 'This string ShouLD be ALL in title CASe';
_.map(s.split(' '), (w) => _.capitalize(w.toLowerCase())).join(' ')
Unless i missed it, lodash doesnt have its own lower/upper case methods.
const titleCase = str =>
str
.split(' ')
.map(str => {
const word = str.toLowerCase()
return word.charAt(0).toUpperCase() + word.slice(1)
})
.join(' ')
You can also split out the map function to do separate words
Below code will work perfectly:
var str = "TITLECASE";
_.startCase(str.toLowerCase());
Not as concise as #4castle's answer, but descriptive and lodash-full, nonetheless...
var basicTitleCase = _
.chain('This string ShouLD be ALL in title CASe')
.toLower()
.words()
.map(_.capitalize)
.join(' ')
.value()
console.log('Result:', basicTitleCase)
console.log('Exact Match:' , basicTitleCase === 'This String Should Be All In Title Case')
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
Here's another solution for my use case:
"devil's backbone"
Simply:
function titleCase (str) {
return _.map(str.split(' '), _.upperFirst).join(' ');
}
Using startCase would remove the apostrophe, so I had to work around that limitation. The other solutions seemed pretty convoluted. I like this as it's clean, easy to understand.
with lodash 4, you can use _.capitalize()
_.capitalize('JOHN')
It returns 'John'
See https://lodash.com/docs/4.17.5#capitalize for details
you can simply use the lowdash capitalize methode , it Converts the first character of string to upper case and the remaining to lower case.
https://lodash.com/docs/#capitalize
const str = 'titlecase this string ';
_.capitalize(str); //Titlecase This String

Get first letter of each word in a string, in JavaScript

How would you go around to collect the first letter of each word in a string, as in to receive an abbreviation?
Input: "Java Script Object Notation"
Output: "JSON"
I think what you're looking for is the acronym of a supplied string.
var str = "Java Script Object Notation";
var matches = str.match(/\b(\w)/g); // ['J','S','O','N']
var acronym = matches.join(''); // JSON
console.log(acronym)
Note: this will fail for hyphenated/apostrophe'd words Help-me I'm Dieing will be HmImD. If that's not what you want, the split on space, grab first letter approach might be what you want.
Here's a quick example of that:
let str = "Java Script Object Notation";
let acronym = str.split(/\s/).reduce((response,word)=> response+=word.slice(0,1),'')
console.log(acronym);
I think you can do this with
'Aa Bb'.match(/\b\w/g).join('')
Explanation: Obtain all /g the alphanumeric characters \w that occur after a non-alphanumeric character (i.e: after a word boundary \b), put them on an array with .match() and join everything in a single string .join('')
Depending on what you want to do you can also consider simply selecting all the uppercase characters:
'JavaScript Object Notation'.match(/[A-Z]/g).join('')
Easiest way without regex
var abbr = "Java Script Object Notation".split(' ').map(function(item){return item[0]}).join('');
This is made very simple with ES6
string.split(' ').map(i => i.charAt(0)) //Inherit case of each letter
string.split(' ').map(i => i.charAt(0)).toUpperCase() //Uppercase each letter
string.split(' ').map(i => i.charAt(0)).toLowerCase() //lowercase each letter
This ONLY works with spaces or whatever is defined in the .split(' ') method
ie, .split(', ') .split('; '), etc.
string.split(' ') .map(i => i.charAt(0)) .toString() .toUpperCase().split(',')
To add to the great examples, you could do it like this in ES6
const x = "Java Script Object Notation".split(' ').map(x => x[0]).join('');
console.log(x); // JSON
and this works too but please ignore it, I went a bit nuts here :-)
const [j,s,o,n] = "Java Script Object Notation".split(' ').map(x => x[0]);
console.log(`${j}${s}${o}${n}`);
#BotNet flaw:
i think i solved it after excruciating 3 days of regular expressions tutorials:
==> I'm a an animal
(used to catch m of I'm) because of the word boundary, it seems to work for me that way.
/(\s|^)([a-z])/gi
Try -
var text = '';
var arr = "Java Script Object Notation".split(' ');
for(i=0;i<arr.length;i++) {
text += arr[i].substr(0,1)
}
alert(text);
Demo - http://jsfiddle.net/r2maQ/
Using map (from functional programming)
'use strict';
function acronym(words)
{
if (!words) { return ''; }
var first_letter = function(x){ if (x) { return x[0]; } else { return ''; }};
return words.split(' ').map(first_letter).join('');
}
Alternative 1:
you can also use this regex to return an array of the first letter of every word
/(?<=(\s|^))[a-z]/gi
(?<=(\s|^)) is called positive lookbehind which make sure the element in our search pattern is preceded by (\s|^).
so, for your case:
// in case the input is lowercase & there's a word with apostrophe
const toAbbr = (str) => {
return str.match(/(?<=(\s|^))[a-z]/gi)
.join('')
.toUpperCase();
};
toAbbr("java script object notation"); //result JSON
(by the way, there are also negative lookbehind, positive lookahead, negative lookahead, if you want to learn more)
Alternative 2:
match all the words and use replace() method to replace them with the first letter of each word and ignore the space (the method will not mutate your original string)
// in case the input is lowercase & there's a word with apostrophe
const toAbbr = (str) => {
return str.replace(/(\S+)(\s*)/gi, (match, p1, p2) => p1[0].toUpperCase());
};
toAbbr("java script object notation"); //result JSON
// word = not space = \S+ = p1 (p1 is the first pattern)
// space = \s* = p2 (p2 is the second pattern)
It's important to trim the word before splitting it, otherwise, we'd lose some letters.
const getWordInitials = (word: string): string => {
const bits = word.trim().split(' ');
return bits
.map((bit) => bit.charAt(0))
.join('')
.toUpperCase();
};
$ getWordInitials("Java Script Object Notation")
$ "JSON"
How about this:
var str = "", abbr = "";
str = "Java Script Object Notation";
str = str.split(' ');
for (i = 0; i < str.length; i++) {
abbr += str[i].substr(0,1);
}
alert(abbr);
Working Example.
If you came here looking for how to do this that supports non-BMP characters that use surrogate pairs:
initials = str.split(' ')
.map(s => String.fromCodePoint(s.codePointAt(0) || '').toUpperCase())
.join('');
Works in all modern browsers with no polyfills (not IE though)
Getting first letter of any Unicode word in JavaScript is now easy with the ECMAScript 2018 standard:
/(?<!\p{L}\p{M}*)\p{L}/gu
This regex finds any Unicode letter (see the last \p{L}) that is not preceded with any other letter that can optionally have diacritic symbols (see the (?<!\p{L}\p{M}*) negative lookbehind where \p{M}* matches 0 or more diacritic chars). Note that u flag is compulsory here for the Unicode property classes (like \p{L}) to work correctly.
To emulate a fully Unicode-aware \b, you'd need to add a digit matching pattern and connector punctuation:
/(?<!\p{L}\p{M}*|[\p{N}\p{Pc}])\p{L}/gu
It works in Chrome, Firefox (since June 30, 2020), Node.js, and the majority of other environments (see the compatibility matrix here), for any natural language including Arabic.
Quick test:
const regex = /(?<!\p{L}\p{M}*)\p{L}/gu;
const string = "Żerard Łyżwiński";
// Extracting
console.log(string.match(regex)); // => [ "Ż", "Ł" ]
// Extracting and concatenating into string
console.log(string.match(regex).join("")) // => ŻŁ
// Removing
console.log(string.replace(regex, "")) // => erard yżwiński
// Enclosing (wrapping) with a tag
console.log(string.replace(regex, "<span>$&</span>")) // => <span>Ż</span>erard <span>Ł</span>yżwiński
console.log("_Łukasz 1Żukowski".match(/(?<!\p{L}\p{M}*|[\p{N}\p{Pc}])\p{L}/gu)); // => null
In ES6:
function getFirstCharacters(str) {
let result = [];
str.split(' ').map(word => word.charAt(0) != '' ? result.push(word.charAt(0)) : '');
return result;
}
const str1 = "Hello4 World65 123 !!";
const str2 = "123and 456 and 78-1";
const str3 = " Hello World !!";
console.log(getFirstCharacters(str1));
console.log(getFirstCharacters(str2));
console.log(getFirstCharacters(str3));
Output:
[ 'H', 'W', '1', '!' ]
[ '1', '4', 'a', '7' ]
[ 'H', 'W', '!' ]
This should do it.
var s = "Java Script Object Notation",
a = s.split(' '),
l = a.length,
i = 0,
n = "";
for (; i < l; ++i)
{
n += a[i].charAt(0);
}
console.log(n);
The regular expression versions for JavaScript is not compatible with Unicode on older than ECMAScript 6, so for those who want to support characters such as "å" will need to rely on non-regex versions of scripts.
Event when on version 6, you need to indicate Unicode with \u.
More details: https://mathiasbynens.be/notes/es6-unicode-regex
Yet another option using reduce function:
var value = "Java Script Object Notation";
var result = value.split(' ').reduce(function(previous, current){
return {v : previous.v + current[0]};
},{v:""});
$("#output").text(result.v);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id="output"/>
This is similar to others, but (IMHO) a tad easier to read:
const getAcronym = title =>
title.split(' ')
.map(word => word[0])
.join('');
ES6 reduce way:
const initials = inputStr.split(' ').reduce((result, currentWord) =>
result + currentWord.charAt(0).toUpperCase(), '');
alert(initials);
Try This Function
const createUserName = function (name) {
const username = name
.toLowerCase()
.split(' ')
.map((elem) => elem[0])
.join('');
return username;
};
console.log(createUserName('Anisul Haque Bhuiyan'));

Convert camelCaseText to Title Case Text

How can I convert a string either like 'helloThere' or 'HelloThere' to 'Hello There' in JavaScript?
const text = 'helloThereMister';
const result = text.replace(/([A-Z])/g, " $1");
const finalResult = result.charAt(0).toUpperCase() + result.slice(1);
console.log(finalResult);
capitalize the first letter - as an example. Note the space in " $1".
Of course, in case the first letter is already capital - you would have a spare space to remove.
Alternatively using lodash:
lodash.startCase(str);
Example:
_.startCase('helloThere');
// ➜ 'Hello There'
Lodash is a fine library to give shortcut to many everyday js tasks.There are many other similar string manipulation functions such as camelCase, kebabCase etc.
I had a similar problem and dealt with it like this:
stringValue.replace(/([A-Z]+)*([A-Z][a-z])/g, "$1 $2")
For a more robust solution:
stringValue.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1")
http://jsfiddle.net/PeYYQ/
Input:
helloThere
HelloThere
ILoveTheUSA
iLoveTheUSA
Output:
hello There
Hello There
I Love The USA
i Love The USA
Example without side effects.
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();
});
}
In ES6
const camel2title = (camelCase) => camelCase
.replace(/([A-Z])/g, (match) => ` ${match}`)
.replace(/^./, (match) => match.toUpperCase())
.trim();
The best string I've found for testing camel-case-to-title-case functions is this ridiculously nonsensical example, which tests a lot of edge cases. To the best of my knowledge, none of the previously posted functions handle this correctly:
__ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser_456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D
This should be converted to:
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
If you want just a simple function that handles cases like the one above (and more cases than many of the previously answers), here's the one I wrote. This code isn't particularly elegant or fast, but it's simple, understandable, and works.
The snippet below contains an online runnable example:
var mystrings = [ "__ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser_456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D", "helloThere", "HelloThere", "ILoveTheUSA", "iLoveTheUSA", "DBHostCountry", "SetSlot123ToInput456", "ILoveTheUSANetworkInTheUSA", "Limit_IOC_Duration", "_This_is_a_Test_of_Network123_in_12__days_", "ASongAboutTheABCsIsFunToSing", "CFDs", "DBSettings", "IWouldLove1Apple", "Employee22IsCool", "SubIDIn", "ConfigureABCsImmediately", "UseMainNameOnBehalfOfSubNameInOrders" ];
// Take a single camel case string and convert it to a string of separate words (with spaces) at the camel-case boundaries.
//
// E.g.:
// __ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser_456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D
// --> 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 --> I 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 // "__ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser_456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D"
.replace(/(_)+/g, ' ') // " ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser 456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D"
.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() // "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"
;
// capitalize the first letter
return result.charAt(0).toUpperCase() + result.slice(1);
}
for (var i = 0; i < mystrings.length; i++) {
jQuery(document.body).append("<br />\"");
jQuery(document.body).append(camelCaseToTitleCase(mystrings[i]));
jQuery(document.body).append("\"<br>(was: \"");
jQuery(document.body).append(mystrings[i]);
jQuery(document.body).append("\") <br />");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
Based on one of the examples above I came up with this:
const camelToTitle = (camelCase) => camelCase
.replace(/([A-Z])/g, (match) => ` ${match}`)
.replace(/^./, (match) => match.toUpperCase())
.trim()
It works for me because it uses .trim() to handle the edge case where the first letter is capitalized and you end up with a extra leading space.
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim
Ok, I'm a few years late to the game, but I had a similar question, and I wanted to make a one-replace solution for every possible input. I must give most of the credit to #ZenMaster in this thread and #Benjamin Udink ten Cate in this thread.
Here's the code:
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 < textArray.length; i++){
text = textArray[i];
text = text.replace(camelEdges,'$1 ');
text = text.charAt(0).toUpperCase() + text.slice(1);
resultArray.push(text);
}
It has three clauses, all using lookahead to prevent the regex engine from consuming too many characters:
[A-Z](?=[A-Z][a-z]) looks for a capital letter that is followed by a capital then a lowercase. This is to end acronyms like USA.
[^A-Z](?=[A-Z]) looks for a non-capital-letter followed by a capital letter. This ends words like myWord and symbols like 99Bottles.
[a-zA-Z](?=[^a-zA-Z]) looks for a letter followed by a non-letter. This ends words before symbols like BFG9000.
This question was at the top of my search results, so hopefully I can save others some time!
Here's my version of it. It adds a space before every UpperCase english letter that comes after a lowercase english letter and also capitalizes the first letter if needed:
For example:
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;
}
This implementation takes consecutive uppercase letters and numbers in consideration.
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));
});
Expected output:
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
You can use a function like this:
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"
Code with a bunch of test strings here: http://jsfiddle.net/jfriend00/FWLuV/.
Alternate version that keeps leading spaces here: http://jsfiddle.net/jfriend00/Uy2ac/.
One more solution based on RegEx.
respace(str) {
const regex = /([A-Z])(?=[A-Z][a-z])|([a-z])(?=[A-Z])/g;
return str.replace(regex, '$& ');
}
Explanation
The above RegEx consist of two similar parts separated by OR operator. The first half:
([A-Z]) - matches uppercase letters...
(?=[A-Z][a-z]) - followed by a sequence of uppercase and lowercase letters.
When applied to sequence FOo, this effectively matches its F letter.
Or the second scenario:
([a-z]) - matches lowercase letters...
(?=[A-Z]) - followed by an uppercase letter.
When applied to sequence barFoo, this effectively matches its r letter.
When all replace candidates were found, the last thing to do is to replace them with the same letter but with an additional space character. For this we can use '$& ' as a replacement, and it will resolve to a matched substring followed by a space character.
Example
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"]
If you deal with Capital Camel Case this snippet can help you, also it contains some specs so you could be sure that it matches appropriate to your case.
export const fromCamelCaseToSentence = (word) =>
word
.replace(/([A-Z][a-z]+)/g, ' $1')
.replace(/([A-Z]{2,})/g, ' $1')
.replace(/\s{2,}/g, ' ')
.trim();
And specs:
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')
})
})
My split case solution which behaves the way I want:
const splitCase = s => !s || s.indexOf(' ') >= 0 ? s :
(s.charAt(0).toUpperCase() + s.substring(1))
.split(/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/g)
.map(x => x.replace(/([0-9]+)/g,'$1 '))
.join(' ')
Input
'a,abc,TheId,TheID,TheIDWord,TheID2Word,Leave me Alone!'
.split(',').map(splitCase)
.forEach(x => console.log(x))
Output
A
Abc
The Id
The ID
The ID Word
The ID2 Word
Leave me Alone!
As this above function requires Lookbehind in JS which isn't currently implemented in Safari, I've rewritten the implementation to not use RegEx below:
const isUpper = c => c >= 'A' && c <= 'Z'
const isDigit = c => c >= '0' && c <= '9'
const upperOrDigit = c => isUpper(c) || isDigit(c)
function splitCase(s) {
let to = []
if (typeof s != 'string') return to
let lastSplit = 0
for (let i=0; i<s.length; i++) {
let c = s[i]
let prev = i>0 ? s[i-1] : null
let next = i+1 < s.length ? s[i+1] : null
if (upperOrDigit(c) && (!upperOrDigit(prev) || !upperOrDigit(next))) {
to.push(s.substring(lastSplit, i))
lastSplit = i
}
}
to.push(s.substring(lastSplit, s.length))
return to.filter(x => !!x)
}
try this library
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"
Using JS's String.prototype.replace() and String.prototype.toUpperCase()
const str = "thisIsATestString";
const res = str.replace(/^[a-z]|[A-Z]/g, (c, i) => (i? " " : "") + c.toUpperCase());
console.log(res); // "This Is A Test String"
The most compatible answer for consecutive capital-case words is this:
const text = 'theKD';
const result = text.replace(/([A-Z]{1,})/g, " $1");
const finalResult = result.charAt(0).toUpperCase() + result.slice(1);
console.log(finalResult);
It's also compatible with The KD and it will not convert it to The K D.
None of the answers above worked perfectly for me, so had to come with own bicycle:
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');
}
Test cases:
null => ''
'' => ''
'simpleString' => 'Simple String'
'stringWithABBREVIATIONInside => 'String With ABBREVIATION Inside'
'stringWithNumber123' => 'String With Number 123'
'complexExampleWith123ABBR890Etc' => 'Complex Example With 123 ABBR 890 Etc'
This works for me check this out
CamelcaseToWord("MyName"); // returns My Name
function CamelcaseToWord(string){
return string.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1");
}
I didn't try everyone's answer, but the few solutions I tinkered with did not match all of my requirements.
I was able to come up with something that did...
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(),
'')
I think this can be done just with the reg exp /([a-z]|[A-Z]+)([A-Z])/g and replacement "$1 $2".
ILoveTheUSADope -> I Love The USA Dope
Below is link which demonstrates camel case string to sentence string using regex.
Input
myCamelCaseSTRINGToSPLITDemo
Output
my Camel Case STRING To SPLIT Demo
This is regex for conversion of camel case to sentence text
(?=[A-Z][a-z])|([A-Z]+)([A-Z][a-rt-z][a-z]\*)
with $1 $2 as subsitution.
Click to view the conversion on regex
Input
javaScript
Output
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");
HTTPRequest_ToServer-AndWaiting --> HTTP Request To Server And Waiting
function toSpaceCase(str) {
return str
.replace(/[-_]/g, ' ')
/*
* insert a space between lower & upper
* HttpRequest => Http Request
*/
.replace(/([a-z])([A-Z])/g, '$1 $2')
/*
* space before last upper in a sequence followed by lower
* XMLHttp => XML Http
*/
.replace(/\b([A-Z]+)([A-Z])([a-z])/, '$1 $2$3')
// uppercase the first character
.replace(/^./, str => str.toUpperCase())
.replace(/\s+/g, ' ')
.trim();
}
const input = 'HTTPRequest_ToServer-AndWaiting';
const result = toSpaceCase(input);
console.log(input,'-->', result)
Undercover C programmer. If like me you want to preserve acronyms and don't want to look at cryptic patterns, then perhaps you may like this:
function isUpperCase (str) {
return str === str.toUpperCase()
}
export function camelCaseToTitle (str) {
for (let i = str.length - 1; i > 0; i--) {
if (!isUpperCase(str[i - 1]) && isUpperCase(str[i])) {
str = str.slice(0, i) + ' ' + str.slice(i)
}
}
return str.charAt(0).toUpperCase() + str.slice(1)
}
This solution works also for other Unicode characters which are not in the [A-Z] range. E.g. Ä, Ö, Å.
let camelCaseToTitleCase = (s) => (
s.split("").reduce(
(acc, letter, i) => (
i === 0 || console.log(acc, letter, i)
? [...acc, letter.toUpperCase()]
: letter === letter.toUpperCase()
? [...acc, " ", letter]
: [...acc, letter]
), []
).join("")
)
const myString = "ArchipelagoOfÅland"
camelCaseToTitleCase(myString)
Adding yet another ES6 solution that I liked better after not being happy with a few thoughts above.
https://codepen.io/902Labs/pen/mxdxRv?editors=0010#0
const camelize = (str) => str
.split(' ')
.map(([first, ...theRest]) => (
`${first.toUpperCase()}${theRest.join('').toLowerCase()}`)
)
.join(' ');

Categories

Resources