What's wrong with the first element in HOF in JS? - javascript

Here I have a string with repeated chars,
I want to get the string without repetition, so I used map with specific index, but I don't know what's wrong with the 1st repeated char, when I used slice(i+1,1) all thing was good, but when I used slice(i,1) also all thing was good except the first repeated char.
The output of the 1st code is : elzero
The output of the 2nd code is : eelzero
What's the problem?
Here's the two codes:
let myString = "EElllzzzzzzzeroo";
let elzero = myString
.split("")
.map(function(ele, i = 1, myString) {
console.log(i);
if (myString[i] === myString[i + 1]) {
return myString[i + 1].slice(i + 1, 1);
} else {
return myString[i];
}
})
.join("");
console.log(elzero);
// Elzero
And here's the second:
let myString = "EElllzzzzzzzeroo";
let elzero = myString
.split("")
.map(function(ele, i = 1, myString) {
console.log(i);
if (myString[i] === myString[i + 1]) {
return myString[i].slice(i, 1);
} else {
return myString[i];
}
})
.join("");
console.log(elzero);
// EElzero

Your first code block only works because your .slice() happens to be returning empty strings. You really don't need to use .slice() at all, since all it does is generate an empty string which is then removed when you use .join(). The .slice() call does NOT update/remove an element like .splice() on an array does.
In your second code block, you're doing:
myString[i].slice(i, 1);
If i is 0 then you are on the first character in your string, so myString[0] is "E". Here, .slice(0, 1) says, give me the string that starts at index 0 up to, but not including index 1. This results in "E" being returned.
For all of your subsequent calls myString[i] gives you back one character (so it only has one index, 0), but you're trying to use .slice() to get a portion of your string from indexes that don't exist as i is bigger than your index. Moreover, i is bigger than your second argument, so when i is 1, you're asking to get get the string portion from index 1 (which doesn't exist) up to but not including 1, which results in an empty string. When i is 2, its a similar situation, which results in an empty string.
What you should be doing is removing the use of .slice() altogether, and instead return an empty string when you want to omit the character:
let myString = "EElllzzzzzzzeroo";
let elzero = myString
.split("")
.map(function(ele, i, myString) {
if (ele === myString[i + 1]) { // if current char (ele) equals the next char (myString[i+1]), then "remove" the current char by mapping it to an empty string (this is removed when we `.join("")`)
return "";
} else {
return ele;
}
})
.join("");
console.log(elzero); // Elzero
More concisely, you can rewrite this with arrow functions and a ternary like so. You can also use Array.from() to iterate the code points (ie: characters) within your string, and use the second argument as the mapping function:
const myString = "EElllzzzzzzzeroo";
const elzero = Array.from(
myString,
(ele, i) => ele === myString[i + 1] ? "" : ele
).join("");
console.log(elzero); // Elzero
Alternatively, using a different approach, you can use .replace() with a regular expression to remove repeated characters:
const myString = "EElllzzzzzzzeroo";
const elzero = myString.replace(/(.)\1*/g, '$1')
console.log(elzero); // Elzero
The (.) captures a character and groups it, the \1* is a backreference that matches zero or more of the grouped character repeated, and the "$1" replaces the matched characters with the singular grouped character.

Since you are returning myString[i], not myString[i+1], you have to compare myString[i] with myString[i-1]:
let myString = "EElllzzzzzzzeroo";
let elzero = myString
.split("")
.map(function(ele, i = 1, myString) {
console.log(i);
// if (myString[i] === myString[i + 1]) {
if (myString[i-1] === myString[i]) {
return myString[i].slice(i, 1);
} else {
return myString[i];
}
})
.join("");
console.log(elzero);
// EElzero

Related

JavaScript remove a character from a string and remove the previous character

How do I remove a character from a string and remove the previous character as well?
Example:
"ABCXDEXFGHXIJK"
I want to split the string by "X" and remove the previous character which returns
"ABDFGIJK" // CX, EX, HX are removed
I found this thread but it removes everything before rather than a specific amount of characters: How to remove part of a string before a ":" in javascript?
I can run a for loop but I was wondering if there was a better/simpler way to achieve this
const remove = function(str){
for(let i = 0; i < str.length; i++){
if(str[i] === "X") str = str.slice(0, i - 1) + str.slice(i + 1);
}
return str
}
console.log(remove("ABCXDEXFGHXIJK")) // ABDFGIJK
You can use String.prototype.replace and regex.
"ABCXDEXFGHXIJK".replace(/.X/g, '')
The g at the end is to replace every occurrence of .X. You can use replaceAll as well, but it has less support.
"ABCXDEXFGHXIJK".replaceAll(/.X/g, '')
If you want it to be case insensitive, use the i flag as well.
"ABCXDEXFGHXIJK".replace(/.x/gi, '')
The simplest way is to use a regular expression inside replace.
"ABCXDEXFGHXIJK".replace(/.X/g, "")
.X means "match the combination of X and any single character before it, g flag after the expression body repeats the process globally (instead of doing it once).
While not the most computationally efficient, you could use the following one-liner that may meet your definition of "a better/simpler way to achieve this":
const remove = str => str.split("X").map((ele, idx) => idx !== str.split("X").length - 1 ? ele.slice(0, ele.length - 1) : ele).join("");
console.log(remove("ABCXDEXFGHXIJK"));
Maybe you can use recursion.
function removeChar(str, char){
const index = str.indexOf(char);
if(index < 0) return str;
// removes 2 characters from string
return removeChar(str.split('').splice(index - 2, index).join());
}
Try this way (Descriptive comments are added in the below code snippet itself) :
// Input string
const str = "ABCXDEXFGHXIJK";
// split the input string based on 'X' and then remove the last item from each element by using String.slice() method.
const splittedStrArr = str.split('X').map(item => item = item.slice(0, -1));
// Output by joining the modified array elements.
console.log(splittedStr.join(''))
By using RegEx :
// Input string
const str = "ABCXDEXFGHXIJK";
// Replace the input string by matching the 'X' and one character before that with an empty string.
const modifiedStr = str.replace(/.X/g, "")
// Output
console.log(modifiedStr)

How do I create a function that takes a string and returns dashes on the left and right side of every vowel (a e i o u)

Examples
dashed("Carpe Diem") ➞ "C-a-rp-e- D-i--e-m"
dashed("Fight for your right to party!") ➞ "F-i-ght f-o-r y-o--u-r r-i-ght t-o- p-a-rty!"
Notes
There are already a couple of solutions using regex; therefore, I am adding an answer which can be useful to someone who is not familiar with regex.
The following function, referenced by formatVowels, iterates the parameter string and uses String#indexOf to check if any of the characters is a vowel; if yes, it prepends and appends - to it and then adds the resulting text to the variable, result, otherwise, adds the character as it is to the variable, result.
const formatVowels = (str) => {
if (str == undefined) return "";
let result = "";
for (const ch of str) {
result += "AEIOU".indexOf(ch.toUpperCase()) != -1 ? "-" + ch + "-" : ch;
}
return result;
};
// Test
console.log(formatVowels('Hello'));
const my_replacer = (str)=> str.replace(/[aeiouAEIOU]/g,'-$&-')
let a = 'Carpe Diem'
console.log(my_replacer(a))
let b = 'Fight for your right to party!'
console.log(my_replacer(b))
coolString = `Cookke`;
function dashed(coolString) {
const regex = /a|e|i|o|u/gi;
console.log(coolString.replace(regex, `-$&-`));
}
dashed(coolString);

How to remove the (.) in a string and then display every alphabetic character with a dot

I would like to have a a function who takes a string a parameter, removes the dots, loops trough every alphabetic character and display like this (A.B.C.) when input is (A..B..C) for example.
How can I build this function?
Here for I have the next function in mind, unfortunately is not working I get a output result like this (hfff) when input string is "h..f.ff", would like to have this output (H.F.F.F)
function filter (initials) {
let result = initials.replace(/\./g, '')
let i;
for (i = 0; i < result.length; i++) {
result[i] + ".";
}
return result
console.log(result)
}
const initials = "h..f.ff"
console.log(filter(initials))
You could use split, map and join
function filter(initials) {
return initials.replace(/[^a-z]/gi, '') // Remove non-letters
.toUpperCase()
.split('') // Convert to an Array
.map(l => l + '.') // Add dots
.join(''); // Join
}
const initials = "h..f.ff";
console.log(filter(initials));
You need to assign this
result[i] + ".";
to something. Do:
let i,newresult;
for (i = 0; i < result.length; i++) {
newresult += result[i] + ".";
}
well you can:
make the string uppercase
split the string char-by-char
filter only letters
join using "."
function format(string){
return string.toUpperCase()
.split("")
.filter(c => /[a-zA-Z]/.test(c))
.join(".")
}
format("h..f.ff") // "H.F.F.F"
Use replaceAll to remove all . char with nothing.
Then from that string, make all letters uppercase.
From that string, split the whole word up into and array of letters using split (Each piece of the string on each side of the parameter passed to split gets turned into an element in a new array. if you leave the parameter blank, it's just each character in the string)
Finally join each those elements together with a . between them using join
function filter (initials) {
initials=initials.replaceAll('.','');
initials=initials.toUpperCase();
initials=initials.split('');
initials=initials.join('.');
return initials;
}
var test = "h..f..t....e.Z";
console.log(filter(test));
Thanks #blex for the snippet advice

Javascript - Replace a character inside a substring of a string

I have a string like "this/ is an example abc/def/fgh/uio to give you an example"
I'd like to target the longest word and replace on this substring any "/" by a "+".
I manage to identify the longest word and I would know how to replace ALL "/" by a "+" BUT I don't know how to replace the "/" only in the longest word.
Here's what I've got so far
//identify longest word in string
function longestWord(str) {
var words = str.split(' ');
return words.reduce(longer);
}
function longer(champ, contender) {
return (contender.length > champ.length) ? contender: champ;
}
//purely given an exemple, some strigns won't be exactly like this
var text2 = "this/ is an example abc/def/fgh/uio to give you an example"
if (longestWord(text2) > 30 ) {
text2.replace(/\//g, ' / ');
}
The problem is this will also replace the "/" on the substring "this/", and I don't want that.
How to achieve this?
Your longestWord function returns the longest word in the string, so you can pass that string alone (not a regular expression) as the first argument to .replace, and replace with (the second argument) the /\//g called on that longest word:
function getLongestWord(str) {
var words = str.split(' ');
return words.reduce(longer);
}
function longer(champ, contender) {
return (contender.length > champ.length) ? contender: champ;
}
var text2 = "this/ is an example abc/def/fgh/uio to give you an example"
const longestWord = getLongestWord(text2);
const output = text2.replace(longestWord, longestWord.replace(/\//g, '+'));
console.log(output);
#CertainPermance's solution is far more elegant (and I think performant) than this, but as I'd written the answer I thought I may as well put it in.
It's fairly similar, in truth, though in this instance we get the index of the word and use that to perform the replace, which at the time of writing I thought was necessary. Now looking at the better solution, I realise such a check is not needed, as the longest word in a string will not feature in any other words, so it's easy and safe to simply perform a replace on it.
const data = "this/ is an example abc/def/fgh/uio to give you an example";
const getLongestWordIndex = stringIn => stringIn
.split(' ')
.reduce(
(prev, curr, i) => curr.length > prev.length ? {
index: i,
length: curr.length
} : prev,
{
length: -1,
index: -1
}
).index
const replaceLongestWord = (sentence, replacer) => {
const longestWordIndex = getLongestWordIndex(sentence);
const words = data.split(' ');
return Object.values({
...words,
[longestWordIndex]: replacer(words[longestWordIndex])
}).join(' ')
}
const wordReplaceFunction = word => word.replace(/\//g, '+')
const result = replaceLongestWord(data, wordReplaceFunction);
console.dir(result)

Replace nth occurrence javascript

in this example string '1,2,3,4,5' I am trying to capture and replace the 3rd occurence of the comma , character
this code here
'1,2,3,4,5'.match(/(?:[^,]*,){2}[^,]*(,)/)
matches 1,2,3 and the comma im looking for
but not sure how to replace just the comma
'1,2,3,4,5'.replace(/(?:[^,]*,){2}[^,]*(,)/, "$")
replaces everything before 4 giving $4,5
i just want a string result like 1,2,3$4,5 for example
I have achieved this task in two different ways, with array split and slice and with a String#replace that takes a callback
//splice
let parts = [];
let str = "1,2,3,4,5";
let formatted = ((parts = str.split(",")).slice(0,3)).join("-") + ' ' + parts.slice(3).join(":")
​
//callback
let str = "1,2,3,4,5";
str.replace(/,/g, (() => {
let count = 0;
return (match, position) => {
count += 1;
if(count == 3) return ' ';
else if(count < 3) return '-';
else return ':';
});
})())
Is this even possible with a plain String#replace?
You can use capturing group and replace by first capturing group
.replace(/((?:[^,]*,){2}[^,]*),/g, "$1:");
^ ^
The captured group will capture the matched string except the third comma which is $1 in the replacement string.
console.log('1,2,3,4,5,2,3,4,5,2,3,4,5'.replace(/((?:[^,]*,){2}[^,]*),/g, "$1:"));

Categories

Resources