Javascript Regular expression with replace - javascript

I'm working on a project on search about emoji and replace it with icon
but I have some problem on regular expression, Below mentioned is my code for reference:
var f = ["( :3 )" , "( :P )","\(:star:\)"];
var re = function(s){return new RegExp(s, 'g');};
now when I'm going to search about emoji and replace it as shown below:
s = "hello :D how are you :P dwdwd";
for(var n in f){
var m;
if ((m = re(f[n]).exec(s)) !== null) {
m.forEach((match, groupIndex) => {
s = s.replace(match,"<img src='http://abs.twimg.com/emoji/v1/72x72/"+ r[n] +".png'>");
});
}}
In this case, it works well and replace the emoji. But it only replace when there are space before and after emoji what should i do to replace the emoji in the begin of string or end !
s = ":D hello how are you :)";
This case is not working. How can i edit my regular expression for being able to replace emoji at begin and end of string and at the same time if its found in middle of string & have space between word and emoji
My 2nd problem with regular expression is "\(:star:\)" it never replaces. While it must replace word :star: with an emoji but i think i miss some thing on regular expression for it.

You can use beginning & ending anchors along with pipe to achieve this. For example:
/(^:3\s)|(\s:3\s)|(\s:3$)/g
^ is an anchor which matches :3\s to the beginning of the string.
$ is an anchor which matches \s:3 to the end of the string.
\s matches whitespace.
| is the pipe operator which acts as a logical OR operator between the different capture groups.

Just remove the spaces from your emoji regex.
var f = ["(:3)", "(:P)", "\(:star:\)"];
var r = ["[sadface]", "[toungeface]", "[staremoji]"];
var re = function(s) {
return new RegExp(s, 'g');
};
s = "hello :3 how are you :P dwdwd :star: :3";
console.log(s);
for (var n in f) {
var m;
if ((m = re(f[n]).exec(s)) !== null) {
m.forEach((match, groupIndex) => {
s = s.replace(match, r[n]);
});
}
}
console.log(s);

var content = "hello :D how are you :P dwdwd";
content = content.replace(/((:D|:P))/g,function(match){
var result = "";
var index = -1;
switch(match)
{
case ":D":
result = "happy";
index = 0
break;
case ":P":
result = "smilie";
index = 1
break;
}
if(index != -1)
{
return "<img src='http://abs.twimg.com/emoji/v1/72x72/"+index+".png'>";
}
return result;
});
console.log(content);
Please try this.

I created a more generic solution, starting with the mapping of emojis to the relevant names. Rather than two lists that need to be kept in synch, I used a single object:
const emojis = {
'(c)': 'a9',
'(r)': 'ae',
'(tm)': '2122'
//, ...
};
This strikes me as a much more useful structure to work with, but the code below could easily be altered to deal with the two-lists version.
Then I use a helper function to escape characters which are not allowed as plain text in Regular Expression by prepending them with \:
const escapeSpecials = (() => {
const specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'];
const reg = new RegExp('(\\' + specials.join('|\\') + ')', 'g');
return str => str.replace(reg, '\\$1');
})();
Then I have the key function:
const replaceStringsWith = (emojis, convert) => str => Object.keys(emojis).reduce(
(str, em) => str.replace(new RegExp(`(^|\\s+)(${escapeSpecials(em)})($|\\s+)`, 'g'),
(m, a, b, c) => `${a}${convert(emojis[b], b)}${c}`),
str
);
This takes an object containing string/replacement pairs and a converter function which accepts the replacement and gives you back the final form. It returns a function which takes a string, and then searches for any matches on the keys of the object (properly checked for strings or string ends), replacing them with the result of calling the converter on the object's value for the particular key.
Thus we can do:
const toUrl = (name) => `<img src='http://abs.twimg.com/emoji/v1/72x72/${name}.png'>`;
const replaceEmojis = replaceStringsWith(emojis, toUrl)
and call it as
const s = "This is Copyright (c) 2017, FooBar is (tm) BazCo (r)";
replaceEmojis(s); //=>
// `This is Copyright <img src='http://abs.twimg.com/emoji/v1/72x72/a9.png'>
// 2017, FooBar is <img src='http://abs.twimg.com/emoji/v1/72x72/2122.png'>
// BazCo <img src='http://abs.twimg.com/emoji/v1/72x72/ae.png'>`
Note that the converter also takes a second parameter. So you could instead use
const toUrl = (name, emoji) =>
`<img src='http://abs.twimg.com/emoji/v1/72x72/${name}.png' title='${emoji}'>`;
to get
//=> `This is Copyright <img
// src='http://abs.twimg.com/emoji/v1/72x72/a9.png' title='(c)'>
// 2017, FooBar is <img src='http://abs.twimg.com/emoji/v1/72x72/2122.png'
// title='(tm)'> BazCo <img src='http://abs.twimg.com/emoji/v1/72x72/ae.png' title='(r)'>"

Related

How to get the characters / words that lie on both sides, between which our selected character fall?

Let's consider a string str which is defined as :
const str = " 'I am going' - 'I' "
and a function calc() which can be used as :
console.log( calc(str) ) // => am going
So, I decided to make the calc() using regex ! So here is what I thought about.
const calc = (str) => {
const reg = // Not understanding how to get the strings between which '-' falls
str = str.replace(reg, function(_, a) {
const b = remove(a[0], a[1])
return b
})
return str
}
remove() is a function for removing words from string, I made. You can freely modify my code if there is anything incorrect. It's an example how I imagined. So, please help me completing my function !
You could split the string at - and get the content within '' suing match. Then, create a dynamic regex using the RegExp constructor and replace all the instance of second match from the first match
function calc(str) {
const [first, second] = str.split(/\s*-\s*/)
.map(s => s.match(/'([^']+)'/)[1])
return first.replace(new RegExp(second, "g"), '')
}
console.log(calc("'I am going' - 'I'"))
console.log(calc("'Remove this from this string' - 'this'"))
If matchAll is supported in your environment, you could also:
const [first, second] = Array.from(str.matchAll(/'([^']+)'/g), ([,m]) => m)

How can I replace multiple characters in a string?

I want to create a regex with following logic:
1., If string contains T replace it with space
2., If string contains Z remove Z
I wrote two regex already, but I can't combine them:
string.replace(/\T/g,' ') && string.replace(/\Z/g,'');
EDIT: I want the regex code to be shorter
Doesn't seem this even needs regex. Just 2 chained replacements would do.
var str = '[T] and [Z] but not [T] and [Z]';
var result = str.replace('T',' ').replace('Z','');
console.log(result);
However, a simple replace only replaces the first occurence.
To replace all, regex still comes in handy. By making use of the global g flag.
Note that the characters aren't escaped with \. There's no need.
var str = '[T] and [Z] and another [T] and [Z]';
var result = str.replace(/T/g,' ').replace(/Z/g,'');
console.log(result);
// By using regex we could also ignore lower/upper-case. (the i flag)
// Also, if more than 1 letter needs replacement, a character class [] makes it simple.
var str2 = '(t) or (Ⓣ) and (z) or (Ⓩ). But also uppercase (T) or (Z)';
var result2 = str2.replace(/[tⓉ]/gi,' ').replace(/[zⓏ]/gi,'');
console.log(result2);
But if the intention is to process really big strings, and performance matters?
Then I found out in another challenge that using an unnamed callback function inside 1 regex replace can prove to be faster. When compared to using 2 regex replaces.
Probably because if it's only 1 regex then it only has to process the huge string once.
Example snippet:
console.time('creating big string');
var bigstring = 'TZ-'.repeat(2000000);
console.timeEnd('creating big string');
console.log('bigstring length: '+bigstring.length);
console.time('double replace big string');
var result1 = bigstring.replace(/[t]/gi,'X').replace(/[z]/gi,'Y');
console.timeEnd('double replace big string');
console.time('single replace big string');
var result2 = bigstring.replace(/([t])|([z])/gi, function(m, c1, c2){
if(c1) return 'X'; // if capture group 1 has something
return 'Y';
});
console.timeEnd('single replace big string');
var smallstring = 'TZ-'.repeat(5000);
console.log('smallstring length: '+smallstring.length);
console.time('double replace small string');
var result3 = smallstring.replace(/T/g,'X').replace(/Z/g,'Y');
console.timeEnd('double replace small string');
console.time('single replace small string');
var result4 = smallstring.replace(/(T)|(Z)/g, function(m, c1, c2){
if(c1) return 'X';
return 'Y';
});
console.timeEnd('single replace small string');
Do you look for something like this?
ES6
var key = {
'T': ' ',
'Z': ''
}
"ATAZATA".replace(/[TZ]/g, (char) => key[char] || '');
Vanilla
"ATAZATA".replace(/[TZ]/g,function (char) {return key[char] || ''});
or
"ATAZATA".replace(/[TZ]/g,function (char) {return char==='T'?' ':''});
you can capture both and then decide what to do in the callback:
string.replace(/[TZ]/g,(m => m === 'T' ? '' : ' '));
var string = 'AZorro Tab'
var res = string.replace(/[TZ]/g,(m => m === 'T' ? '' : ' '));
console.log(res)
-- edit --
Using a dict substitution you can also do:
var string = 'AZorro Tab'
var dict = { T : '', Z : ' '}
var re = new RegExp(`[${ Object.keys(dict).join('') }]`,'g')
var res = string.replace(re,(m => dict[m] ) )
console.log(res)
Second Update
I have developed the following function to use in production, perhaps it can help someone else. It's basically a loop of the native's replaceAll Javascript function, it does not make use of regex:
function replaceMultiple(text, characters){
for (const [i, each] of characters.entries()) {
const previousChar = Object.keys(each);
const newChar = Object.values(each);
text = text.replaceAll(previousChar, newChar);
}
return text
}
Usage is very simple:
const text = '#Please send_an_information_pack_to_the_following_address:';
const characters = [
{
"#":""
},
{
"_":" "
},
]
const result = replaceMultiple(text, characters);
console.log(result); //'Please send an information pack to the following address:'
Update
You can now use replaceAll natively.
Outdated Answer
Here is another version using String Prototype. Enjoy!
String.prototype.replaceAll = function(obj) {
let finalString = '';
let word = this;
for (let each of word){
for (const o in obj){
const value = obj[o];
if (each == o){
each = value;
}
}
finalString += each;
}
return finalString;
};
'abc'.replaceAll({'a':'x', 'b':'y'}); //"xyc"

Bold part of String

What is the best way to bold a part of string in Javascript?
I have an array of objects. Each object has a name. There is also an input parameter.
If, for example, you write "sa" in input, it automatically searches in array looking for objects with names that contain "sa" string.
When I print all the names, I want to bold the part of the name that coincide with the input text.
For example, if I search for "Ma":
Maria
Amaria
etc...
I need a solution that doesn't use jQuery. Help is appreciated.
PD: The final strings are in the tag. I create a list using angular ng-repeat.
This is the code:
$scope.users = data;
for (var i = data.length - 1; i >= 0; i--) {
data[i].name=data[i].name.replace($scope.modelCiudad,"<b>"+$scope.modelCiudad+"</b>");
};
ModelCiudad is the input text content var. And data is the array of objects.
In this code if for example ModelCiudad is "ma" the result of each is:
<b>Ma</b>ria
not Maria
You can use Javascript's str.replace() method, where str is equal to all of the text you want to search through.
var str = "Hello";
var substr = "el";
str.replace(substr, '<b>' + substr + '</b>');
The above will only replace the first instance of substr. If you want to handle replacing multiple substrings within a string, you have to use a regular expression with the g modifier.
function boldString(str, substr) {
var strRegExp = new RegExp(substr, 'g');
return str.replace(strRegExp, '<b>'+substr+'</b>');
}
In practice calling boldString would looks something like:
boldString("Hello, can you help me?", "el");
// Returns: H<b>el</b>lo can you h<b>el</b>p me?
Which when rendered by the browser will look something like: Hello can you help me?
Here is a JSFiddle with an example: https://jsfiddle.net/1rennp8r/3/
A concise ES6 solution could look something like this:
const boldString = (str, substr) => str.replace(RegExp(substr, 'g'), `<b>${substr}</b>`);
Where str is the string you want to modify, and substr is the substring to bold.
ES12 introduces a new string method str.replaceAll() which obviates the need for regex if replacing all occurrences at once. It's usage in this case would look something like this:
const boldString = (str, substr) => str.replaceAll(substr, `<b>${substr}</b>`);
I should mention that in order for these latter approaches to work, your environment must support ES6/ES12 (or use a tool like Babel to transpile).
Another important note is that all of these approaches are case sensitive.
Here's a pure JS solution that preserves the original case (ignoring the case of the query thus):
const boldQuery = (str, query) => {
const n = str.toUpperCase();
const q = query.toUpperCase();
const x = n.indexOf(q);
if (!q || x === -1) {
return str; // bail early
}
const l = q.length;
return str.substr(0, x) + '<b>' + str.substr(x, l) + '</b>' + str.substr(x + l);
}
Test:
boldQuery('Maria', 'mar'); // "<b>Mar</b>ia"
boldQuery('Almaria', 'Mar'); // "Al<b>mar</b>ia"
I ran into a similar problem today - except I wanted to match whole words and not substrings. so if const text = 'The quick brown foxes jumped' and const word = 'foxes' than I want the result to be 'The quick brown <strong>foxes</strong> jumped'; however if const word = 'fox', than I expect no change.
I ended up doing something similar to the following:
const pattern = `(\\s|\\b)(${word})(\\s|\\b)`;
const regexp = new RegExp(pattern, 'ig'); // ignore case (optional) and match all
const replaceMask = `$1<strong>$2</strong>$3`;
return text.replace(regexp, replaceMask);
First I get the exact word which is either before/after some whitespace or a word boundary, and then I replace it with the same whitespace (if any) and word, except the word is wrapped in a <strong> tag.
Here is a version I came up with if you want to style words or individual characters at their index in react/javascript.
replaceAt( yourArrayOfIndexes, yourString/orArrayOfStrings )
Working example: https://codesandbox.io/s/ov7zxp9mjq
function replaceAt(indexArray, [...string]) {
const replaceValue = i => string[i] = <b>{string[i]}</b>;
indexArray.forEach(replaceValue);
return string;
}
And here is another alternate method
function replaceAt(indexArray, [...string]) {
const startTag = '<b>';
const endTag = '</b>';
const tagLetter = i => string.splice(i, 1, startTag + string[i] + endTag);
indexArray.forEach(tagLetter);
return string.join('');
}
And another...
function replaceAt(indexArray, [...string]) {
for (let i = 0; i < indexArray.length; i++) {
string = Object.assign(string, {
[indexArray[i]]: <b>{string[indexArray[i]]}</b>
});
}
return string;
}
Above solutions are great, but are limited! Imagine a test scenerio where you want to match case insensitive query in a string and they could be multiple matches.
For example
Query: ma
String: The Amazing Spiderman
Expected Result: The Amazing Spiderman
For above scenerio, use this:
const boldMatchText = (text,searchInput) => {
let str = text.toLowerCase();
const query = searchInput.toLowerCase();
let result = "";
let queryLoc = str.indexOf(query);
if (queryLoc === -1) {
result += text;
} else
do {
result += ` ${text.substr(0, queryLoc)}
<b>${text.substr(queryLoc, query.length)}</b>`;
str = str.substr(queryLoc + query.length, str.length);
text = text.substr(queryLoc + query.length, str.length);
queryLoc = str.indexOf(query);
} while (text.length > 0 && queryLoc !== -1);
return result + text;
};

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 hyphens to camel case (camelCase)

With regex (i assume) or some other method, how can i convert things like:
marker-image or my-example-setting to markerImage or myExampleSetting.
I was thinking about just splitting by - then convert the index of that hypen +1 to uppercase. But it seems pretty dirty and was hoping for some help with regex that could make the code cleaner.
No jQuery...
Try this:
var camelCased = myString.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
The regular expression will match the -i in marker-image and capture only the i. This is then uppercased in the callback function and replaced.
This is one of the great utilities that Lodash offers if you are enlightened and have it included in your project.
var str = 'my-hyphen-string';
str = _.camelCase(str);
// results in 'myHyphenString'
You can get the hypen and the next character and replace it with the uppercased version of the character:
var str="marker-image-test";
str.replace(/-([a-z])/g, function (m, w) {
return w.toUpperCase();
});
Here's my version of camelCase function:
var camelCase = (function () {
var DEFAULT_REGEX = /[-_]+(.)?/g;
function toUpper(match, group1) {
return group1 ? group1.toUpperCase() : '';
}
return function (str, delimiters) {
return str.replace(delimiters ? new RegExp('[' + delimiters + ']+(.)?', 'g') : DEFAULT_REGEX, toUpper);
};
})();
It handles all of the following edge cases:
takes care of both underscores and hyphens by default (configurable with second parameter)
string with unicode characters
string that ends with hyphens or underscore
string that has consecutive hyphens or underscores
Here's a link to live tests: http://jsfiddle.net/avKzf/2/
Here are results from tests:
input: "ab-cd-ef", result: "abCdEf"
input: "ab-cd-ef-", result: "abCdEf"
input: "ab-cd-ef--", result: "abCdEf"
input: "ab-cd--ef--", result: "abCdEf"
input: "--ab-cd--ef--", result: "AbCdEf"
input: "--ab-cd-__-ef--", result: "AbCdEf"
Notice that strings that start with delimiters will result in a uppercase letter at the beginning.
If that is not what you would expect, you can always use lcfirst.
Here's my lcfirst if you need it:
function lcfirst(str) {
return str && str.charAt(0).toLowerCase() + str.substring(1);
}
Use String's replace() method with a regular expression literal and a replacement function.
For example:
'uno-due-tre'.replace(/-./g, (m) => m[1].toUpperCase()) // --> 'unoDueTre'
Explanation:
'uno-due-tre' is the (input) string that you want to convert to camel case.
/-./g (the first argument passed to replace()) is a regular expression literal.
The '-.' (between the slashes) is a pattern. It matches a single '-' character followed by any single character. So for the string 'uno-due-tre', the pattern '-.' matches '-d' and '-t' .
The 'g' (after the closing slash) is a flag. It stands for "global" and tells replace() to perform a global search and replace, ie, to replace all matches, not just the first one.
(m) => m[1].toUpperCase() (the second argument passed to replace()) is the replacement function. It's called once for each match. Each matched substring is replaced by the string this function returns. m (the first argument of this function) represents the matched substring. This function returns the second character of m uppercased. So when m is '-d', this function returns 'D'.
'unoDueTre' is the new (output) string returned by replace(). The input string is left unchanged.
This doesn't scream out for a RegExp to me. Personally I try to avoid regular expressions when simple string and array methods will suffice:
let upFirst = word =>
word[0].toUpperCase() + word.toLowerCase().slice(1)
let camelize = text => {
let words = text.split(/[-_]/g) // ok one simple regexp.
return words[0].toLowerCase() + words.slice(1).map(upFirst)
}
camelize('marker-image') // markerImage
Here is my implementation (just to make hands dirty)
/**
* kebab-case to UpperCamelCase
* #param {String} string
* #return {String}
*/
function toUpperCamelCase(string) {
return string
.toLowerCase()
.split('-')
.map(it => it.charAt(0).toUpperCase() + it.substring(1))
.join('');
}
// Turn the dash separated variable name into camelCase.
str = str.replace(/\b-([a-z])/g, (_, char) => char.toUpperCase());
Here is another option that combines a couple answers here and makes it method on a string:
if (typeof String.prototype.toCamel !== 'function') {
String.prototype.toCamel = function(){
return this.replace(/[-_]([a-z])/g, function (g) { return g[1].toUpperCase(); })
};
}
Used like this:
'quick_brown'.toCamel(); // quickBrown
'quick-brown'.toCamel(); // quickBrown
You can use camelcase from NPM.
npm install --save camelcase
const camelCase = require('camelcase');
camelCase('marker-image'); // => 'markerImage';
camelCase('my-example-setting'); // => 'myExampleSetting';
Another take.
Used when...
var string = "hyphen-delimited-to-camel-case"
or
var string = "snake_case_to_camel_case"
function toCamelCase( string ){
return string.toLowerCase().replace(/(_|-)([a-z])/g, toUpperCase );
}
function toUpperCase( string ){
return string[1].toUpperCase();
}
Output: hyphenDelimitedToCamelCase
is also possible use indexOf with recursion for that task.
input some-foo_sd_dsd-weqe
output someFooSdDsdWeqe
comparison ::: measure execution time for two different scripts:
$ node camelCased.js
someFooSdDsdWeqe
test1: 2.986ms
someFooSdDsdWeqe
test2: 0.231ms
code:
console.time('test1');
function camelCased (str) {
function check(symb){
let idxOf = str.indexOf(symb);
if (idxOf === -1) {
return str;
}
let letter = str[idxOf+1].toUpperCase();
str = str.replace(str.substring(idxOf+1,idxOf+2), '');
str = str.split(symb).join(idxOf !== -1 ? letter : '');
return camelCased(str);
}
return check('_') && check('-');
}
console.log(camelCased ('some-foo_sd_dsd-weqe'));
console.timeEnd('test1');
console.time('test2');
function camelCased (myString){
return myString.replace(/(-|\_)([a-z])/g, function (g) { return g[1].toUpperCase(); });
}
console.log(camelCased ('some-foo_sd_dsd-weqe'));
console.timeEnd('test2');
Just a version with flag, for loop and without Regex:
function camelCase(dash) {
var camel = false;
var str = dash;
var camelString = '';
for(var i = 0; i < str.length; i++){
if(str.charAt(i) === '-'){
camel = true;
} else if(camel) {
camelString += str.charAt(i).toUpperCase();
camel = false;
} else {
camelString += str.charAt(i);
}
}
return camelString;
}
Use this if you allow numbers in your string.
Obviously the parts that begin with a number will not be capitalized, but this might be useful in some situations.
function fromHyphenToCamelCase(str) {
return str.replace(/-([a-z0-9])/g, (g) => g[1].toUpperCase())
}
function fromHyphenToCamelCase(str) {
return str.replace(/-([a-z0-9])/g, (g) => g[1].toUpperCase())
}
const str1 = "category-123";
const str2 = "111-222";
const str3 = "a1a-b2b";
const str4 = "aaa-2bb";
console.log(`${str1} => ${fromHyphenToCamelCase(str1)}`);
console.log(`${str2} => ${fromHyphenToCamelCase(str2)}`);
console.log(`${str3} => ${fromHyphenToCamelCase(str3)}`);
console.log(`${str4} => ${fromHyphenToCamelCase(str4)}`);
You can also use string and array methods; I used trim to avoid any spaces.
const properCamel = (str) =>{
const lowerTrim = str.trim().toLowerCase();
const array = lowerTrim.split('-');
const firstWord = array.shift();
const caps = array.map(word=>{
return word[0].toUpperCase() + word.slice(1);
})
caps.unshift(firstWord)
return caps.join('');
}
This simple solution takes into account these edge cases.
Single word
Single letter
No hyphen
More than 1 hyphen
const toCamelCase = (text) => text.replace(/(.)([^-|$]*)[-]*/g, (_,letter,word) => `${letter.toUpperCase()}${word.toLowerCase()}`)

Categories

Resources