Convert sentence or camelCase word to spinal-case - javascript

I am trying to convert both sentence case and camel case to spinal case.
I am able to change camel case to by adding a space before every capital letter, but when I apply it to sentences with capital letters after spaces, I get extra spacing.
Here is my function so far :
function spinalCase(str) {
var noCamel = str.replace(/([A-Z])/g, ' $1');
var newStr = noCamel.replace(/\s|_/g, "-");
return newStr.toLowerCase();
}
spinalCase("makeThisSpinal"); //returns make-this-spinal
spinalCase("Make This Spinal"); //returns -make--this--spinal

Get lodash, specifically, https://lodash.com/docs#kebabCase.
_.kebabCase('makeThisSpinal') // make-this-spinal
_.kebabCase('Even Sentences Work') // even-sentences-work

Instead of:
var noCamel = str.replace(/([A-Z])/g, ' $1');
Try:
var noCamel = str.replace(/(\B[A-Z])/g, ' $1');

It's because you're replacing all capital letters with a space and its lowercase letter. So in your sentence, you're getting two spaces before this and spinal.
What you can do is replace all uppercase letters with "-$1" and then just remove all spaces from the string.

function spinalCase(str) {
var noCamel = str.replace(/([a-z](?=[A-Z]))/g, '$1 ')
var newStr = noCamel.replace(/\s|_/g, "-");
return newStr.toLowerCase();
}
spinalCase("makeThisSpinal"); //returns make-this-spinal
spinalCase("Make This Spinal"); //returns -make-this-spinal
Instead of str.replace(/([A-Z])/g, ' $1') for the camel case split, you should use str.replace(/([a-z](?=[A-Z]))/g, '$1 ') which will space out each word regardless of case.

Here's my solution, perhaps you will find it good reference:
function spinalCase(str) {
var newStr = str[0];
for (var j = 1; j < str.length; j++) {
// if not a letter make a dash
if (str[j].search(/\W/) !== -1 || str[j] === "_") {
newStr += "-";
}
// if a Capital letter is found
else if (str[j] === str[j].toUpperCase()) {
// and preceded by a letter or '_'
if (str[j-1].search(/\w/) !== -1 && str[j-1] !== "_") {
// insert '-' and carry on
newStr += "-";
newStr += str[j];
}
else {
newStr += str[j];
}
}
else {
newStr += str[j];
}
}
newStr = newStr.toLowerCase();
return newStr;
}

Related

Is there a way to match every letter in a string and insert a specific letter in their place?

For example if I had the string "GCG", I'd like to insert a
"C" at every "G" match, and a "G" at every "C" match, making it GCCGGC.
So far I have the following, but it prints GCGCGC.
function pairElement(str) {
for(i = 0; i < str.length; i++) {
if(str[i] == "G") {
return str.replace(/([GC+/])/g, "GC");
} else if (str[i] == "C") {
return str.replace(/([?=CG+/])/g, "CG");
}
}
}
pairElement("GCG");
Edit: I think only the first if statement is executing and not running the else if. Are there any other methods I can use to search for different letters, not only one, and insert another letter depending on what the search for letter is?
You can convert the string into array using splitand then iterate through the array and replace each character.
Then you can use join to convert the array into string.
var string = 'GCG';
var str = string.split('').map(c => {
if(c === 'G') c = 'GC';
else if (c === 'C') c = 'CG';
return c;
}).join('');
console.log('String ' + string);
console.log('New String ' + str);
you can do
function pairElement(str) {
return str.replace(/G|C/g, e => e=='G'?'GC':'CG')
}
console.log(pairElement("GCG"));
You are not using recursion. Once it hits the return statement, the control exits. A better way would be to use regex as one of the answers suggested but if you want to just make tiny modifications in your own code, maybe try something like this.
function pairElement(str) {
var newStr= ""; // using new string to make it more readible
for(i = 0; i < str.length; i++) {
if(str[i] == "G") {
newStr = newStr + str[i] + "C";
} else if (str[i] == "C") {
newStr = newStr + str[i] + "G";
} else {
newStr = newStr + str[i]; //you didn't specify what do you want to do in this case
}
}
return newStr;
}
pairElement("GCG");

Debugging JavaScript for Palindrome Function

function palindrome(str) {
str = str.replace(' ', '');
str = str.replace(',', '');
str = str.replace('.', '');
str = str.toLowerCase();
if (str.length % 2 === 0) {
var x = 0;
while (x < (str.length - x)) {
if (str.charAt(x) === str.charAt((str.length - x) - 1)) {
x++;
} else {
return false;
}
}
return true;
} else {
var y = 0;
while (y < (str.length - y - 1)) {
if (str.charAt(y) === str.charAt((str.length - y) - 1)) {
y++;
} else {
return false;
}
}
return true;
}
}
palindrome("eye");
This may not be the most effecient way of solving this, but I begin by remove extraneous characters, then I used an if/else to split out even and odd string lengths. Within each, I only check equality of characters up through the middle of the word - since past that would be repetitious.
However, after multiple changes and looking into other solutions for the problem, I still cannot get mine to pass for a particular case: palindrome("never odd or even")
If it helps, it passes for "race car" and "almostomla" and "eye".
Thanks in advance!
The problem is that the native replace Javascript function is only replacing a single occurrence in the string. Use Regex to account for all of the matches within the string.
However, keep in mind that the "." character is used in Regex as a wildcard so you need to escape it with a backslash to tell Regex you're specifically looking for the "." character. See this JSFiddle as an example: https://jsfiddle.net/on333yf9/3/
function palindrome(str) {
str = str.replace(/ /g, '');
str = str.replace(/,/g, '');
str = str.replace(/\./g, '');
str = str.toLowerCase();
if (str.length % 2 === 0) {
var x = 0;
while (x < (str.length - x)) {
if (str.charAt(x) === str.charAt((str.length - x) - 1)) {
x++;
} else {
return false;
}
}
return true;
} else {
var y = 0;
while (y < (str.length - y - 1)) {
if (str.charAt(y) === str.charAt((str.length - y) - 1)) {
y++;
} else {
return false;
}
}
return true;
}
}
The problem is because of the following lines:
str = str.replace(' ', '');
str = str.replace(',', '');
str = str.replace('.', '');
It does replace all white spaces, commas or dots globally, it just replaces one space, comma and dot, if it's there. You have to find all spaces, commas and dots and remove them. This is what you can do,
str = str.replace(/ /g, '');
str = str.replace(/,/g, '');
str = str.replace(/./g, '');
The g character means to repeat the search through the entire string. Read about this, and other RegEx modifiers available in JavaScript here.
Edited:
You can do something like this:
if(str.replace(/ /g, '').length != 0){
str = str.replace(/ /g, '');
}
if(str.replace(/,/g, '').length != 0){
str = str.replace(/,/g, '');
}
if(str.replace(/\./g, '').length != 0){
str = str.replace(/\./g, '');
}
Unless you want to write your own code why not user reverse/join?
function palindrome(str)
{
str = str.split(' ').join('');
str = str.split(',').join('');
str = str.split('.').join('');
str = str.toLowerCase();
if (str.split('').reverse().join('') == str)
{
return true;
}
else
{
return false;
}
}
palindrome("never odd or even");

Formatting negative numbers with regex

I need to format my numbers and I am using regex /(?=(?!^)(?:\d{3})+$)/g, to replace and insert , where it is necessary. But currently I have an issue with negative {3} 000 numbers, so comma is added after minus.
What am I doing wrong?
'-200'.replace(/(?=(?!^)(?:\d{3})+$)/g, ',')
returns: -,200
correct: -200
'-2000'.replace(/(?=(?!^)(?:\d{3})+$)/g, ',')
returns: -2,000
correct: -2,000
You can use this regex:
var num = '-2000';
var repl = num.replace(/(\d)(?=(?:\d{3})+$)/m, '$1,');
or
var repl = num.replace(/(?=(?:\B\d{3})+$)/m, ',');
RegEx Demo
I suggest you to replace ^ with \b
(?=(?!\b)(?:\d{3})+$)
DEMO
(?!^) asserts that we are not at the start only, but (?!\b) asserts that we are not between a word char and a non-word character (vice-versa).
Example:
alert('-200'.replace(/(?=(?!\b)(?:\d{3})+$)/g, ','))
alert('-2000'.replace(/(?=(?!\b)(?:\d{3})+$)/g, ','))
To handle signed numbers, I'd recommend using something else than a regex
function formatInteger(num) {
var str = ('' + num).split('.')[0];
var sign = (str.charAt(0) === '-') && '-' || '';
if (sign) {
str = str.substr(1);
}
return sign + str.split('').reduceRight(function (result, char) {
if (result.length % 4 === 0) {
char += ',';
}
return char + result;
}, '').slice(0, -1);
}
If you feed this function a float, it will be truncated.
formatInteger(123456.123); // "123,456"
formatInteger(-1594504924) // "-1,594,504,924"
An other way:
var nb = '-2000000';
nb = nb.split(/\B/).reduce(function(p, c, i, a) {
return p + ((a.length-i)%3 ? c : ',' + c);
});

Regex to allow numbers, plus symbol, minus symbol and brackets

I am trying to create a regex that allows only the following 0-9, plus symbol, minus symbol and brackets (). No limitations on length of each of the mentioned. So far I have this but it does not seem to work.
/^[0-9 -+]+$/
Hyphen - has to be at the end of charlist, else it means interval.
/^[0-9 ()+-]+$/
0-9 is possible to write shortly as \d
/^[\d ()+-]+$/
This should work for you:
^[\d\(\)\-+]+$
^ -> start of string
\d -> same as [0-9]
+ -> one or more repetitions
$ -> end of string
DEMO
var re = /^[\d\(\)\-+]+$/m;
var str = ['09+()1213+-','fa(-ds'];
var m;
var result = "";
for(var i = 0; i < str.length; i++) {
if ((m = re.exec(str[i])) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
}
result += "\""+str[i]+ "\"" + " is matched:" + (m != null) + "</br>";
}
document.getElementById("results").innerHTML = result
<div id="results"></div>
To match digits, +, -, (, and ) use:
[+()\d-]+
The trick is the position of the characters inside the character class.
if (/^[+()\d-]+$/.test(text)) {
} else {
}
var re = /^[\w\(\)\-\!\+\*\&\%\$#\#\[\]\{\}\<\>\s]+$/m;
var str = ['09+()1213+-[#test#gmail{}<>','fa(-ds'];
var m;
var result = "";
for(var i = 0; i < str.length; i++) {
if ((m = re.exec(str[i])) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
}
result += "\""+str[i]+ "\"" + " is matched:" + (m != null) + "</br>";
}
document.getElementById("results").innerHTML = result
<div id="results"></div>
[\d\(\)\+\-\(\)]
That should do it.
EDIT: But since some agree the escaping is too much, here ya go:
[\d+()-]

Is there a way I can change the contents of a variable in Camel Case to space separated words?

I have a variable which contains this:
var a = "hotelRoomNumber";
Is there a way I can create a new variable from this that contains: "Hotel Room Number" ? I need to do a split on the uppercase character but I've not seen this done anywhere before.
Well, you could use a regex, but it's simpler just to build a new string:
var a = "hotelRoomNumber";
var b = '';
if (a.length > 0) {
b += a[0].toUpperCase();
for (var i = 1; i != a.length; ++i) {
b += a[i] === a[i].toUpperCase() ? ' ' + a[i] : a[i];
}
}
// Now b === "Hotel Room Number"
var str = "mySampleString";
str = str.replace(/([A-Z])/g, ' $1').replace(/^./, function(str){ return str.toUpperCase(); });
http://jsfiddle.net/PrashantJ/zX8RL/1/
I have made a function here:
http://jsfiddle.net/wZf6Z/2/
function camelToSpaceSeperated(string)
{
var char, i, spaceSeperated = '';
// iterate through each char
for (i = 0; i < string.length; i++) {
char = string.charAt(i); // current char
if (i > 0 && char === char.toUpperCase()) { // if is uppercase
spaceSeperated += ' ' + char;
} else {
spaceSeperated += char;
}
}
// Make the first char uppercase
spaceSeperated = spaceSeperated.charAt(0).toUpperCase() + spaceSeperated.substr(1);
return spaceSeperated;
}
The general idea is to iterate through each char in the string, check if the current char is already uppercased, if so then prepend a space to it.

Categories

Resources