0
\$\begingroup\$

I have a class with a property of grid[][] and each value is either true or false. I need to convert this to a string with letters o and b in place of the boolean.

First way, simple for loops over the array and return the string:

 get rle() {
     let result = "";
     for(let y = 0; y < this.grid.length; y++) {
         for(let x =0; x < this.grid[y].length; x++) {
             result += ( (this.grid[y][x]) ?  "o" : "b" );
         }
     }
     return result;
}

Or a more JS style solution?

get rle() {
    return this.grid.reduce( (total, currentValue, currentIndex, arr) => {
        return total + arr[currentIndex].reduce( (total, currentValue, currentIndex, arr) => {
            return total + ( (arr[currentIndex]) ?  "o" : "b" );
        }, "");
    }, "");
 }

Is this a good JS style solution, and what in your opinion is better? I prefer the first because anyone can instantly understand it. The JS solution makes me frown with 3 nested returns, looks odd.

\$\endgroup\$
2
\$\begingroup\$

First, a few points of the code you wrote. If you have an array of values, you can join the values together to efficiently create a string. This would eliminate the need for at least one of the reduce calls. Second, in a reduce call, the value of the second callback parameter (currentValue in your code) is the value of the array parameter at the index parameter (arr[currentIndex] in your code). Combining that with Javascript's capability to ignore excess function parameters, your reduce calls should take only two parameters, and use the currentValue in place of the arr[currentIndex].

You should also avoid using the same variable names in the same scope. Having two sets of total, currentValue, currentIndex, and arr could get confusing quickly, and lead to strange bugs.

Now, for the one-liner:

return this.grid.flat().map((el) => el ? "o" : "b").join("");

See Array#flat, Array#map, and the aforementioned Array#join. Of these, Array#flat is the newest and possibly unsupported method. It can be easily polyfilled or replaced. The MDN page shows some clever replacements like arr.reduce((all, row) => all.concat(row), []) and [].concat(...arr).

\$\endgroup\$
  • \$\begingroup\$ Yes, And this method will work faster too... \$\endgroup\$ – Phantom Feb 11 at 12:11
  • \$\begingroup\$ That's the one liner I was looking for. Back to the arrays manual for me.. thanks cbojar. \$\endgroup\$ – Matthew Page Feb 11 at 12:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.