Given a string like Marty Mcfly is there a regex or other one line solution to capitalize the 'f' so I get Marty McFly?
I can always count on the space between first and last and the first letter of the last name (i.e. the M) will always be caps.
I'm pretty open to just about any javascript, jquery, regex solution, I just need it to be short and sweet.
I've got a method that takes the string apart using indexOf and substring but I'm hoping theres a regex or something similar.
You can take advantage of the form of String.replace which takes a function as its second argument:
function fixMarty(s) {
return (""+s).replace(/Mc(.)/g, function(m, m1) {
return 'Mc' + m1.toUpperCase();
});
}
fixMarty('Marty Mcfly'); // => "Marty McFly"
fixMarty("Mcdonald's"); // => "McDonald's"
This is a perfect case for using a callback with .replace().
function fixMc(str) {
return(str.replace(/\bMc(\w)/, function(match, p1) {
return(match.slice(0, -1) + p1.toUpperCase());
}));
}
Here's a jsFiddle http://jsfiddle.net/jfriend00/Qbf8R/ where you can see it in action on a several different test cases.
By way of explanation for the how the callback works, the parameter match is the whole regex match, the parameter p1 is what the first parenthesized group matched and the callback returns what you want to replace the whole regex match with.
var text = 'Marty Mcfly';
text = text.replace(/Mc[a-z]/, function (k)
{
return 'Mc' + k[2].toUpperCase();
}
);
Use a combination of RegEx's exec method and String's replace method:
var name = 'Marty Mcfly',
pattern = /\bmc([a-z])/gi,
match = pattern.exec(name);
if (match) {
alert(name.replace(pattern, 'Mc' + match[1].toUpperCase()));
}
Here's a version that works with "Mac":
var name = 'Connor Macleod',
pattern = /\b(mc|mac)([a-z])/gi,
match = pattern.exec(name);
if (match) {
alert(name.replace(pattern, match[1] + match[2].toUpperCase()));
}
Here's the best I can do:
'Marty Mcfly'.replace(/ mc([a-z])/i, function (str, $1) {return " Mc" + $1.toUpperCase()})
Related
I'd like to replace everything between two characters with another string. I came up with this function:
String.prototype.unformat = function() {
var s='';
for (var i=0; i<this.length;i++) s+=this[i]
return s.replace(/\$[^$]*\$/g, '')
};
Using a string like 'This is a test $33$' and unformat it with the function above, it will return 'This is a test '.
Ok-cool, but I'd like to replace all occurrences in ( $ ... $ ) with the associated char code.
In the example 'This is a test $33$', I like to replace $33$ with the result of the javascript String.fromCharCode() function to get the string 'This is a test !' as result.
How to edit the prototype function above to get the desired result?
Thanks in advance :)
You can use a callback function that returns fromCharCode() with the matched code
String.prototype.unformat = function() {
return this.replace(/\$([^$]*)\$/g, function (string, charcode) {
return String.fromCharCode(charcode);
});
};
console.log(("char: $33$").unformat());
In order to avoid any future problems, I would also adapt the regex to only match digits: /\$(\d+)\$/g
You can use a match group () and replace it with the String.fromCharCode result:
String.prototype.unformat = function() {
return this.replace(/\$(.*?)\$/g, function(match, group) { // the match is the whole match (including the $s), group is the matched group (the thing between the $s)
return String.fromCharCode(group);
});
};
Notes:
No need to copy the string as replace doesn't mutate the original string (this).
The match group (.*?) is a non-greedy one (lazy one) that matches as few characters as possible.
It is better if you don't mess around natives' prototypes (such as String, Number, ...).
Example:
String.prototype.unformat = function() {
return this.replace(/\$(.*?)\$/g, function(match, group) {
return String.fromCharCode(group);
});
};
console.log('This is a test $33$'.unformat());
Working on the following problem:
Create a function called alienLanguage where the input will be a str and the output should capitalize all letters except for the last letter of each word
alienLanguage("My name is John") should return "My NAMe Is JOHn"
This is what I have coded:
function alienLanguage(str){
var words = str.toUpperCase().split(' ').map(function (a) {
return a.replace(a[a.length - 1], a[a.length - 1].toLowerCase())
});
return words.join(' ');
}
All of the example test cases work except for the following:
Expected: '\'THIs Is An EXAMPLe\'', instead got: '\'THIs Is An eXAMPLE\''
Why is the e in eXAMPLE turning lowercase? Shouldn't everything automatically turn upperCase ?
edit: I just realized that there are 2 e's and the first one is being replaced. How can I replace the last e? and isn't the last character specified already?
isn't the last character specified already?
No, you've only specified what character to replace, not where. replace searches the string for the expression.
How can I replace the last e?
Don't use replace at all. It does construct a new string anyway, and you can do that much easier:
function alienLanguage(str) {
return str.split(' ').map(function(a) {
return a.slice(0, -1).toUpperCase() + a.slice(-1).toLowerCase();
}).join(' ');
}
You also could use replace, but would use it with regular expression:
function alienLanguage(str) {
return str.toUpperCase().replace(/.\b/g, function(last) {
// ^^^^^^ matches all characters before a word boundary
return last.toLowerCase();
});
}
You don't need to split the string into words. Just use a positive lookahead assertion in your regex to upper-case all letters that are immediately followed by another letter, like this:
function alienLanguage(str){
return str.replace(/(\w)(?=\w)/g, l => l.toUpperCase())
}
You can use substring. Your replace replaces and replaces the first occurrence of the last character in the words -- definitely what you're after:
function alienLanguage(str){
var words = str.toUpperCase().split(' ').map(function (a) {
return a.length ? a.substring(0, a.length - 2) + a[a.length - 1].toLowerCase() : a;
});
return words.join(' ');
}
As #TatsuyukiIshi said, you need to change the use of replace() for regular assignment. For extra help, here is an updated version of your alienLanguage function:
function alienLanguage(str){
return str.toUpperCase().split(' ').map(function(word) {
return word.slice(0, -1) + word.substr(-1).toLowerCase()
}).join(' ')
}
Fiddle here
Extra notes:
word.slice(0,-1) returns the word minus the last character.
word.substr(-1) returns the last character as a string.
.map() returns an array, so you can call join() directly on the result.
replace() is searching using a pattern (or regular expression) and it replaces all occurrences.
Instead, you want to truncate and create a new string, which is known as assignment in other languages (but strings in JS are immutable). See here for more details.
Try it.
function alienLanguage(str){
var words = str.toUpperCase().split(' ').map(function (a) {
return a.substr(0, a.length - 1) +a[a.length - 1].toLowerCase() + a.substr(a.length - 1 + 1);
});
return words.join(' ');
}
Instead of searching for the letter, just concatenate the uppercase part of the string up to the last letter with the lowercased last letter.
This should do the trick:
function alienLanguage(str) {
return str.split(' ').map(function(a) {
return a.slice(0, -1).toUpperCase() + a.slice(-1).toLowerCase();
}).join(' ');
}
I'm trying to clean strings which has been transformed from word text but I'm stuck on removing special character '…'
By click on button "clean", script removes all dots and only one special character, however I need to remove all of them
Where is my mistake?
Here is my code and plunker with struggles
$scope.string = "My transformed string ………….........…...."
$scope.removeDots = function () {
var em = document.getElementsByTagName('em');
var reg = /\./g;
var hellip = /…/g
angular.forEach(em, function (item) {
if(item.innerText.match(reg)){
item.innerText = process(item.innerText)
}
if (item.innerText.match(hellip)){
item.innerText = item.innerText.replace("…", "")
}
});
};
function process( str ) {
return str.replace( /^([^.]*\.)(.*)$/, function ( a, b, c ) {
return b + c.replace( /\./g, '' );
});
}
There's a few problems here, but they can all be resolved by simply reducing the code to a single regex replace within process that will handle both periods and … entities:
$scope.removeDots = function () {
var em = document.getElementsByTagName('em');
angular.forEach(em, function (item) {
item.innerText = process(item.innerText)
});
};
function process( str ) {
return str.replace( /\.|…/g, '');
}
});
Plunker demo
You replace every occurrence of . in process, but only replace … once.
I don't see why don't you just do something like .replace(/(\.|…)/g, ''); the g modifier makes sure every match is replaced.
You can do both replacements by first replacing the occurrences of … with one point (because it might be the only thing you find), and then replacing any sequence of points by one:
function process( str ) {
return str.replace(/…/g, '.').replace(/\.\.+/g, '.');
}
var test="My transformed string ………….........…....";
console.log(process(test));
One of the reasons your code did not replace everything, is that you used a string as find argument, which will result in one replacement only. By using the regular expression as find argument you can get the effect of the g modifier.
I have following string:
[{par1}, {par2}, ..., {parN}]
And I am capturing this with following regex:
(\{\S*\})
This works fine, and captures in groups my params: $1 = par1, $2 = par2... etc
My question is, I want to do some operation in javascript with all those groups.
I know how to do it for 1 group.
str.replace(new RegExp((\{\S*\}),g),'whatever'+$1) //Probably need to add more escape characters
My question is how to replace $1 to 'whatever+'$1, $2 to 'whatever'+$2... etc
i.e
[{par1},{par2}] ==> [mypar1,mypar2]
EDIT
To explain what i want to do more detailed with parameters:
From [{par1},{par2}] I need to extract par1 and par2, so i can call a function with them, which will return different values:
function translate(par) {
//return different things for every parameter
}
//so finally will be like:
str.replace(new RegExp((\{\S*\}),g),translate($1))
Use callback function as a second argument of String.replace function:
var str = '[{par1}, {par2}, ..., {parN}]',
prefix = 'whatever',
replaced = str.replace(/\{(\S+)\}/g, function (p0, p1) {
// ... some other logic
return prefix + p1;
});
console.log(replaced); // "[whateverpar1, whateverpar2, ..., whateverparN]"
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()}`)