Function to title case a string using javascript - javascript

I'm currently working on a fix where there's an existing function that capitalizes each word of the given string. Each value that comes out of that function is later used to validate other logic.
So right now, that function is capitalizing texts in the wrong way. For example internet of things comes out as Internet Of Things and I need it as Internet of Things
This is the function with an adjustment I made, which is basically if the string contains "of" ignore it:
const cleanValue = value
.replace(/-/g, ' ')
.split(' ')
.map((word, i) => {
return word === 'of' && i != 0 ? word : word[0].toUpperCase() + word.substring(1);
})
.join(' ');
But my boss thinks it's a kind of hacky solution and is asking me to look for a better solution, I'm honestly having a hard time trying to fix this in a better way.
Any advice/ideas anyone could provide me on how to improve this?
Thank you!

If you want to ignore some words then you can change your function like this.
const ignoreWords = ["of", "the", "and"];
const cleanValue = value
.replace(/-/g, ' ')
.split(' ')
.map((word) => {
return ignoreWords.includes(word.toLowerCase()) ? word : word[0].toUpperCase() + word.substring(1);
})
.join(' ');

Not sure I love this idea--and it's not super efficient--but it's flexible enough to accommodate a bunch of arbitrary rules.
You could declare a set of transformers that each have 1) a predicate function that determines whether it handles a particular case, and 2) a function to do the transformation.
The last transformer in the set is the default. Its predicate always returns true, and it does capitalization.
Split the string into words and for each word find a transformer to handle it.
const lowerMiddleWords = ['a', 'at', 'of', 'and', 'the', 'for', 'with'];
const capitalize = (word) => word[0].toUpperCase() + word.substring(1);
const transformers = [
{
predicate: (word, index) => index && lowerMiddleWords.includes(word),
transform: (word) => word,
},
{
predicate: (word, index, phrase) => phrase.includes('hackers'),
transform: (word) => capitalize(word.replaceAll('e', '3')),
},
{
predicate: () => true,
transform: capitalize,
}
]
function transform(string) {
return string.split(' ').map((word, index) => {
const transformer = transformers.find((t) => t?.predicate(word, index, string));
return transformer.transform(word);
}).join(' ');
}
[
"internet of things",
"for the birds",
"at peace with the world",
"the good, the bad, and the ugly",
"capitalize all of the things",
"leet hackers like threes",
].forEach(str => console.log(transform(str)));

So here's a javascript solution.
Suppose that you receive a string with name data
const ignoreWords = ["of", "the", "and"]; //used as references other codes from this post
function stringUpperCase(Data){
let ArrayOfStrings = Data.split(" ");
let ArrayUpperCased = [];
ArrayOfStrings.map((word) =>{
if(!ignoreWords.includes(word.toLowerCase())){
ArrayUpperCased.push(word.charAt(0).toUpperCase() + word.slice(1)); //captalize the word
return;
}
ArrayUpperCased.push(word.toLowerCase());
return ;
})
return ArrayUpperCased.join(" ");
}
stringUpperCase("Test Of Text")
// return 'Test of Text'
In this way you can customize the words that you want to ignore and the ones that you want to Uppercase;

Related

Can this problem be solved using functional programming only?

The prompt was:
Create a function that takes in a string and returns a "URL version" of the string. This simply involves replacing the spaces with %20.
It asked to solve the problem using recursion and using .replace is not allowed.
Here is my solution but I understand the ouputArray is being mutated. Is there any other way to solve this without a mutation?
let inputString = "hello world I am fine";
let outputArray = [];
let stringToUrl = (inputString, n) => {
inputArray = [...inputString]
if(n < inputArray.length) {
if(inputArray[n] !== " ") {
outputArray.push(inputArray[n])
return stringToUrl(inputArray, n+1)
}
else {
outputArray.push("%20")
return stringToUrl(inputArray, n+1)
}
}
return outputArray.join('');
}
console.log(stringToUrl(inputString, 0))
Yes, you can do this with FP. In keeping with How do I ask and answer homework questions?, I won't reply with code, but with pointers.
If you weren't doing this with FP (but still had to write it yourself rather than using the string replace method, etc.), you'd probably use a loop building up a new string by looping through the original string character by character and either adding the original character to the new string or adding %20 to it.
In FP, loops are often done via recursion, and your instructions are to use recursion, so we'll do that instead.
Your function should handle the first character in the string it's given (either keeping it or replacing it with %20), and if that character is the only character, just return that updated "character;" otherwise, it should return the updated character followed by the result of passing the rest of the string (all but that first character) through your function again. That will work through the entire string via recursion, building up the new string. (No need for arrays, string concatenation and substring should be fine.)
Here I have made some changes to your code. Hope this solves your problem.
I don't have to use the second array but make changes to the original array.
let inputString = "hello world I am fine";
let stringToUrl = (inputString, n) => {
inputArray = [...inputString]
if(n < inputArray.length) {
if(inputArray[n] === " ") {
inputArray[n] = "%20"
return stringToUrl(inputArray, n+1)
}
else {
return stringToUrl(inputArray, n+1)
}
}
return inputArray.join('');
}
console.log(stringToUrl(inputString, 0))
const replace = (char: string) => char === ' ' ? '%20' : char;
const convert = (str: string, cache = ''): string => {
const [head, ...tail] = str;
return head
? convert(
tail.join(''),
cache.concat(replace(head))
)
: cache
}
const result = convert("hello world I am fine") // hello%20world%20I%20am%20fine
Playground
I hope this task is not language agnostic, because JS is not best choise in terms of recursion optimization.
One option to do that could be using a call to stringToUrl and use an inner recursive function making use of default parameters passing the values of the variables as function arguments.
For example using an arrow function, and also passing a function as a parameter that does a check to either add %20 to the array with final characters:
const stringToUrl = str => {
const func = (
s,
r = "",
c = s.charAt(0),
f = () => r += c === ' ' ? '%20' : c
) => s.length ? f() && func(s.substr(1), r) : r
return func(str)
}
console.log(stringToUrl("hello world I am fine"));
Output
hello%20world%20I%20am%20fine
const stringToUrl = str => {
const func = (
s,
r = "",
c = s.charAt(0),
f = () => r += c === ' ' ? '%20' : c
) => s.length ? f() && func(s.substr(1), r) : r
return func(str)
}
[
"",
" ",
" ",
"hello world I am fine"
].forEach(s =>
console.log(`[${s}] --> ${stringToUrl(s)}`)
);

How to use regex instead of set to convert exception words to lower case?

This is what I have done so far. I am capitalizing the first alphabet of all the words except 'by','and', 'of', 'it', 'the', 'at' etc., (the list is goes on).
Expected output: Dance by Cow
Output I received was : Dance by Cow
But now I want to use regex for this, instead of Set. (reduces space complexity).
Also I wanted to know how to split in a scenario where there is '-' & '_' in an array of words?
let titleCase = str => {
const exceptions = new Set(['by', 'and']); // handling the specific words
if (typeof str == 'number') {
str = JSON.stringify(str);
}
return str
.toLowerCase()
.split('-')
.map(s =>
exceptions.has(s) ? s : s.charAt(0).toUpperCase() + s.substring(1)
)
.join(' ');
};
toTitleCase('dance-by-cow');

Split after regex max without losing delimeter

I'd like to transform a string like:
hello!world.what?up into ["hello!", "world.", "what?", "up"]
.split(/[?=<\.\?\!>]+/) is close to what I'm after, which returns:
["hello", "world", "what", "up"]
.split(/(?=[\?\!\.])/) is a bit closer yet, which returns:
["hello", "!world", ".what", "?up"]
This does the trick, but it's not pretty:
.split(/(?=[\?\!\.])/).map((s, idx, arr) => { (idx > 0) s = s.slice(1); return idx < arr.length - 1 ? s + arr[idx+1][0] : s }).filter(s => s)
How would I rephrase this to achieve the desired output?
Edit: Updated question.
Not sure of the real requirement but to accomplish what you want you could use .match instead of .split.
const items =
'hello!world.what?'.match(/\w+\W/g);
console.log(items);
update after comment
You could add a group for any character you want to use as the terminator for each part.
const items =
'hello!world.what?'.match(/\w+[!.?]/g);
console.log(items);
additional update
the previous solution would only select alphanumeric chars before the !.?
If you want to match any char except the delimiters then use
const items =
'hello!world.what?up'.match(/[^!.?]+([!.?]|$)/g);
console.log(items);
One solution could be first to use replace() for add a token after each searched character, then you can split by this token.
let input = "hello!world.what?";
const customSplit = (str) =>
{
let token = "#";
return str.replace(/[!.?]/g, (match) => match + "#")
.split(token)
.filter(Boolean);
}
console.log(customSplit(input));

Converting any string into camel case

How can I convert a string into camel case using javascript regex?
EquipmentClass name or
Equipment className or equipment class name or Equipment Class Name
should all become: equipmentClassName.
Looking at your code, you can achieve it with only two replace calls:
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"
Edit: Or in with a single replace call, capturing the white spaces also in the 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();
});
}
If anyone is using lodash, there is a _.camelCase() function.
_.camelCase('Foo Bar');
// → 'fooBar'
_.camelCase('--foo-bar--');
// → 'fooBar'
_.camelCase('__FOO_BAR__');
// → 'fooBar'
To get camelCase
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());
}
> To get ***C**amel**S**entence**C**ase* or ***P**ascal**C**ase*
var camelSentence = function camelSentence(str) {
return (" " + str).toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, function(match, chr)
{
return chr.toUpperCase();
});
}
Note :
For those language with accents. Do include À-ÖØ-öø-ÿ with the regex as following
.replace(/[^a-zA-ZÀ-ÖØ-öø-ÿ0-9]+(.)/g This is only for one language. For another language, you have to search and find
I just ended up doing this:
String.prototype.toCamelCase = function(str) {
return str
.replace(/\s(.)/g, function($1) { return $1.toUpperCase(); })
.replace(/\s/g, '')
.replace(/^(.)/, function($1) { return $1.toLowerCase(); });
}
I was trying to avoid chaining together multiple replace statements. Something where I'd have $1, $2, $3 in my function. But that type of grouping is hard to understand, and your mention about cross browser problems is something I never thought about as well.
You can use this solution :
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('');
}
In Scott’s specific case I’d go with something like:
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
The regex will match the first character if it starts with a capital letter, and any alphabetic character following a space, i.e. 2 or 3 times in the specified strings.
By spicing up the regex to /^([A-Z])|[\s-_](\w)/g it will also camelize hyphen and underscore type names.
'hyphen-name-format'.toCamelCase() // -> hyphenNameFormat
'underscore_name_format'.toCamelCase() // -> underscoreNameFormat
Reliable, high-performance example:
function camelize(text) {
const a = text.toLowerCase()
.replace(/[-_\s.]+(.)?/g, (_, c) => c ? c.toUpperCase() : '');
return a.substring(0, 1).toLowerCase() + a.substring(1);
}
Case-changing characters:
hyphen -
underscore _
period .
space
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, '' );
}
I was trying to find a JavaScript function to camelCase a string, and wanted to make sure special characters would be removed (and I had trouble understanding what some of the answers above were doing). This is based on c c young's answer, with added comments and the removal of $peci&l characters.
If regexp isn't required, you might want to look at following code I made a long time ago for 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 );
}
I haven't made any performance tests, and regexp versions might or might not be faster.
My ES6 approach:
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"
This function by pass cammelcase such these tests
Foo Bar
--foo-bar--
__FOO_BAR__-
foo123Bar
foo_Bar
function toCamelCase(str)
{
var arr= str.match(/[a-z]+|\d+/gi);
return arr.map((m,i)=>{
let low = m.toLowerCase();
if (i!=0){
low = low.split('').map((s,k)=>k==0?s.toUpperCase():s).join``
}
return low;
}).join``;
}
console.log(toCamelCase('Foo Bar'));
console.log(toCamelCase('--foo-bar--'));
console.log(toCamelCase('__FOO_BAR__-'));
console.log(toCamelCase('foo123Bar'));
console.log(toCamelCase('foo_Bar'));
console.log(toCamelCase('EquipmentClass name'));
console.log(toCamelCase('Equipment className'));
console.log(toCamelCase('equipment class name'));
console.log(toCamelCase('Equipment Class Name'));
Here is a one liner doing the work:
const camelCaseIt = string => string.toLowerCase().trim().split(/[.\-_\s]/g).reduce((string, word) => string + word[0].toUpperCase() + word.slice(1));
It splits the lower-cased string based on the list of characters provided in the RegExp [.\-_\s] (add more inside the []!) and returns a word array . Then, it reduces the array of strings to one concatenated string of words with uppercased first letters. Because the reduce has no initial value, it will start uppercasing first letters starting with the second word.
If you want PascalCase, just add an initial empty string ,'') to the reduce method.
The top answer is terse but it doesn't handle all edge cases. For anyone needing a more robust utility, without any external dependencies:
function camelCase(str) {
return (str.slice(0, 1).toLowerCase() + str.slice(1))
.replace(/([-_ ]){1,}/g, ' ')
.split(/[-_ ]/)
.reduce((cur, acc) => {
return cur + acc[0].toUpperCase() + acc.substring(1);
});
}
function sepCase(str, sep = '-') {
return str
.replace(/[A-Z]/g, (letter, index) => {
const lcLet = letter.toLowerCase();
return index ? sep + lcLet : lcLet;
})
.replace(/([-_ ]){1,}/g, sep)
}
// All will return 'fooBarBaz'
console.log(camelCase('foo_bar_baz'))
console.log(camelCase('foo-bar-baz'))
console.log(camelCase('foo_bar--baz'))
console.log(camelCase('FooBar Baz'))
console.log(camelCase('FooBarBaz'))
console.log(camelCase('fooBarBaz'))
// All will return 'foo-bar-baz'
console.log(sepCase('fooBarBaz'));
console.log(sepCase('FooBarBaz'));
console.log(sepCase('foo-bar-baz'));
console.log(sepCase('foo_bar_baz'));
console.log(sepCase('foo___ bar -baz'));
console.log(sepCase('foo-bar-baz'));
// All will return 'foo__bar__baz'
console.log(sepCase('fooBarBaz', '__'));
console.log(sepCase('foo-bar-baz', '__'));
Demo here: https://codesandbox.io/embed/admiring-field-dnm4r?fontsize=14&hidenavigation=1&theme=dark
lodash can do the trick sure and well:
var _ = require('lodash');
var result = _.camelCase('toto-ce héros')
// result now contains "totoCeHeros"
Although lodash may be a "big" library (~4kB), it contains a lot of functions that you'd normally use a snippet for, or build yourself.
return "hello world".toLowerCase().replace(/(?:(^.)|(\s+.))/g, function(match) {
return match.charAt(match.length-1).toUpperCase();
}); // HelloWorld
Because this question needed yet another answer...
I tried several of the previous solutions, and all of them had one flaw or another. Some didn't remove punctuation; some didn't handle cases with numbers; some didn't handle multiple punctuations in a row.
None of them handled a string like a1 2b. There's no explicitly defined convention for this case, but some other stackoverflow questions suggested separating the numbers with an underscore.
I doubt this is the most performant answer (three regex passes through the string, rather than one or two), but it passes all the tests I can think of. To be honest, though, I really can't imagine a case where you're doing so many camel-case conversions that performance would matter.
(I added this as an npm package. It also includes an optional boolean parameter to return Pascal Case instead of 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();
});
}
Test cases (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`);
});
To effectively create a function that converts the casing of a string to camel-case, the function will also need to convert each string to lower-case first, before transforming the casing of the first character of non-first strings to an uppercase letter.
My example string is:
"text That I WaNt to make cAMEL case"
Many other solutions provided to this question return this:
"textThatIWaNtToMakeCAMELCase"
What I believe should be the expected, desired output would be this though, where all the mid-string uppercase characters are first transformed to be lowercase:
"textThatIWanrtToMakeCamelCase"
This can be done WITHOUT using any replace() method calls, by utilizing the String.prototype.split(), Array.prototype.map(), and Array.prototype.join() methods:
≤ ES5 Version
function makeCamelCase(str) {
return str
.split(' ')
.map((e,i) => i
? e.charAt(0).toUpperCase() + e.slice(1).toLowerCase()
: e.toLowerCase()
)
.join('')
}
makeCamelCase("text That I WaNt to make cAMEL case")
// -> "textThatIWanrtToMakeCamelCase" ✅
I'll break down what each line does, and then provide the same solution in two other formats— ES6 and as a String.prototype method, though I'd advise against extending built-in JavaScript prototypes directly like this.
Explainer
function makeCamelCase(str) {
return str
// split string into array of different words by splitting at spaces
.split(' ')
// map array of words into two different cases, one for the first word (`i == false`) and one for all other words in the array (where `i == true`). `i` is a parameter that denotes the current index of the array item being evaluated. Because indexes start at `0` and `0` is a "falsy" value, we can use the false/else case of this ternary expression to match the first string where `i === 0`.
.map((e,i) => i
// for all non-first words, use a capitalized form of the first character + the lowercase version of the rest of the word (excluding the first character using the slice() method)
? e.charAt(0).toUpperCase() + e.slice(1).toLowerCase()
// for the first word, we convert the entire word to lowercase
: e.toLowerCase()
)
// finally, we join the different strings back together into a single string without spaces, our camel-cased string
.join('')
}
makeCamelCase("text That I WaNt to make cAMEL case")
// -> "textThatIWanrtToMakeCamelCase" ✅
Condensed ES6+ (One-Liner) Version
const makeCamelCase = str => str.split(' ').map((e,i) => i ? e.charAt(0).toUpperCase() + e.slice(1).toLowerCase() : e.toLowerCase()).join('')
makeCamelCase("text That I WaNt to make cAMEL case")
// -> "textThatIWanrtToMakeCamelCase" ✅
String.prototype method version
String.prototype.toCamelCase = function() {
return this
.split(' ')
.map((e,i) => i
? e.charAt(0).toUpperCase() + e.slice(1).toLowerCase()
: e.toLowerCase()
)
.join('')
}
"text That I WaNt to make cAMEL case".toCamelCase()
// -> "textThatIWanrtToMakeCamelCase" ✅
little modified Scott's answer:
toCamelCase = (string) ->
string
.replace /[\s|_|-](.)/g, ($1) -> $1.toUpperCase()
.replace /[\s|_|-]/g, ''
.replace /^(.)/, ($1) -> $1.toLowerCase()
now it replaces '-' and '_' too.
All 14 permutations below produce the same result of "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());
};
you can use this solution:
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());
Here's my suggestion:
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());
}
or
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());
};
Test cases:
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');
});
});
following #Scott's readable approach, a little bit of fine tuning
// convert any string to camelCase
var toCamelCase = function(str) {
return str.toLowerCase()
.replace( /['"]/g, '' )
.replace( /\W+/g, ' ' )
.replace( / (.)/g, function($1) { return $1.toUpperCase(); })
.replace( / /g, '' );
}
There is my solution:
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'))
This method seems to outperform most answers on here, it's a little bit hacky though, no replaces, no regex, simply building up a new string that's 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;
}
This builds on the answer by CMS by removing any non-alphabetic characters including underscores, which \w does not remove.
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
Upper camel case ("TestString") to lower camel case ("testString") without using regex (let's face it, regex is evil):
'TestString'.split('').reduce((t, v, k) => t + (k === 0 ? v.toLowerCase() : v), '');
I ended up crafting a slightly more aggressive solution:
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('');
}
This one, above, will remove all non-alphanumeric characters and lowercase parts of words that would otherwise remain uppercased, e.g.
Size (comparative) => sizeComparative
GDP (official exchange rate) => gdpOfficialExchangeRate
hello => hello
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('');
}
I know this is an old answer, but this handles both whitespace and _ (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"
const toCamelCase = str =>
str
.replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase())
.replace(/^\w/, c => c.toLowerCase());

How to capitalize all 1st alphabet in the words in a string excluding some cases like 'by'?

This is what I have done so far. I am capitalizing the first alphabet of all the words.
Expected output: Dance by Cow
Output I received was : Dance By Cow
let capitalize = str => {
return str
.toLowerCase()
.split('-')
.map(s => s.charAt(0).toUpperCase() + s.substring(1))
.join(' ');
};
toTitleCase('dance-by-cow');
How about something like this?
const stopwords = new Set (['by', 'with', 'to', 'from', 'and', 'the'])
Then...
.map(s => stopwords.has(s) ? s : s.charAt(0).toUpperCase() + s.substring(1))
At this level it's just conditional code. But, getting a correct set of stopwords isn't a trivial thing to do.
I guess you are on the right track. Maybe one good solution is to create an exceptions array which contains the specific words what you would like to skip from converting the first char to uppercase.
Please find the extended solution:
const toTitleCase = (value) => {
const exceptions = ['by']; // handling the specific words
const handleMapping = s => exceptions.includes(s) ? s : s.charAt(0).toUpperCase() + s.substring(1);
return value.toLowerCase()
.split('-')
.map(handleMapping)
.join(' ');
}
console.log(toTitleCase('dance-by-cow'));
I hope this helps!
Could try something like using, using the second parameter to provide your exclusion words being as you don't specify any other ones in your post.
function toTitleCase(input, exclusions = []) {
return input
.toLowerCase()
.split('-')
.map((word) => {
return exclusions.includes(word) ? word : word.charAt(0).toUpperCase() + word.substring(1);
})
.join(' ');
}
let example = toTitleCase('dance-by-cow', ['by']);
console.log(example);

Categories