Home > Back-end >  What's wrong with the first element in HOF in JS?
What's wrong with the first element in HOF in JS?

Time:04-10

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

CodePudding user response:

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

CodePudding user response:

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.

  • Related