totalnoob
totalnoob

Reputation: 2741

algorithm to compress a string

I want to write a function to compress the characters of a string such as 'bbbab' would be converted to 'b3ab' and I'm getting stuck

it's only printing "b3"

here's the code so far

let string = 'bbbab';
let letters = string.split("");
let currentAlphabetLetter = letters[0];
let count = 0;
let newString = [];

string.split("").forEach(letter => {
    if (letter === currentAlphabetLetter) {
        count++;
    } else {
        if (count > 0) {
            newString.push(`${currentAlphabetLetter}${count}`);
        } else {
        newString.push(`${letter}`);
    }
    count = 0;
    currentAlphabetLetter = letter;
  }
})


console.log(newString);

Upvotes: 1

Views: 148

Answers (3)

Redu
Redu

Reputation: 26161

You may do as follows;

var str = 'bbbabccc',
    res = [...str].reduce((r,c,i) => (r[r.length-1][0] === c || !i) ? (r[r.length-1] += c, r)
                                                                    : r.concat(c), [""])
                  .reduce((r,s) => r + s[0] + (s.length-1 ? s.length : ""), "");
console.log(res);

We have two .reduce()s cascaded here but first it's good to know that [...str] turns into ["b", "b", "b", "a", "b", "c", "c", "c"].

The first .reduce() will reduce it to an array of strings such as ["bbb", "a", "b", "ccc"].

The second .reduce() will further reduce it to the result. The inner mechanics of each reducers are for you to solve.

However, as hint, keep in mind that the comma operator , as in (r[r.length-1] += c, r) takes the last element of r array (accumulator here) adds c to the end of it and returns r.

Upvotes: 1

ernestk
ernestk

Reputation: 72

Like this should work for you

let string = 'bbbab';
let newString = [];

if (string.length < 2) { console.log(string); }
else {
    let letters = string.split("");
    let prev = letters[0];
    let count = 1;
    for( var i = 1; i < letters.length; i++) {
      if (letters[i] !== prev) {
        count > 1 ? newString.push(`${prev}${count}`) : newString.push(`${prev}`);
        count = 1;
      } else {
        count++;
      }
      prev = letters[i];
    }
    /* last element push */
    count > 1 ? newString.push(`${prev}${count}`) : newString.push(`${prev}`);
    console.log(newString.join(""));
}

Upvotes: 0

Barmar
Barmar

Reputation: 780984

When you start a new letter, you need to set count to 1, otherwise you're not counting the first occurrence of the character.

This isn't a problem at the very beginning of the string, because you process the first letter twice: you extract it with let currentAlphabetLetter = letters[0]; and then process it again on the first iteration of the forEach. To make the beginning of the string the same as other occurrences, you should iterate over the substring starting with the 2nd character.

And rather than pushing onto an array, you should append to a string.

When count is 1 you need to append currentAlphabetLetter, not letter.

let string = 'bbbab';
let letters = string.split("");
let currentAlphabetLetter = letters[0];
let count = 1;
let newString = "";

string.substr(1).split("").forEach(letter => {
  if (letter === currentAlphabetLetter) {
    count++;
  } else {
    if (count > 1) {
      newString += `${currentAlphabetLetter}${count}`;
    } else {
      newString += `${currentAlphabetLetter}`;
    }
    count = 1;
    currentAlphabetLetter = letter;
  }
});

// Process the last letter
if (count > 1) {
  newString += `${currentAlphabetLetter}${count}`;
} else {
  newString += `${currentAlphabetLetter}`;
}

console.log(newString);

Upvotes: 1

Related Questions