Is it good a good practice to stringify array?

Viewed 184

Let's say I have an Array consist of Boolean.

myArray = [false,false,false]

And I will need to do different stuff according to every status.

ex :

[false,true,false], [false,false,true], [true,true,false], ...

and so on.

Usually this kind of operation is done by checking each individual element to see fit.

ex:

if(!myArray[0] && myArray[1] && !myArray[2]) do A
if(!myArray[0] && !myArray[1] && myArray[2]) do B
if(myArray[0] && myArray[1] && !myArray[2]) do C
...

Instead of doing that. I convert the array into String:

switch(JSON.stringify(myArray))
    case : "[false,true,false]"
        do A
        break
    case : "[false,false,true]"
        do B
        break
    case : "[true,true,false]"
        do C
        break
    ......

Is this considered good practice? Is there any hidden error I might face with this method? Will this method increase readability ?

3 Answers

Not much wrong with it per se, depends on the context; how many of these booleans are there, where do they come from / what sets them, how many cases, etc. Bad part could be that it can be very hard to understand what is happening and to debug, especially if you have 10+ values in there.

You could perhaps convert each boolean to a string/word that means something in that context, so you get a sentence. If you have a unique word for each boolean, you could leave out the false ones so you only have to write down certain combinations.

Also instead of JSON.stringify() you can use myArray.join(',') which outputs true,true,false (so without the brackets).

Your goal is to write a readable if?
Stringify is a solution, but (maybe only for me) it is a little bit strange.

Here is my advice. Write a function like this:

isEqual(left, right) {
    if (left.length !== right.length) return false;

    for (var i = 0; i < left.length; i++) {
        if (left[i] !== right[i]) return false;
    }

    return true;
}

And use it like this:

if (isEqual(array, [true, false, true]))  alert('isEqual');

About Using JSON.stringify

The use of JSON.stringify will work fine for arrays (of arrays (of arrays...)) of (JSON-compatible) primitives, i.e. boolean, string, number, null. There is no ambiguity. The ECMAScript specification also is clear about the "gap" to produce between distinct values: it should be the empty string, unless explicitly defined differently via the optional argument. See ECMAScript Language Specification on the topic.

One caveat is that undefined is not a thing in JSON, and so [null] and [undefined] would both be stringified to "[null]". But since you are only using false and true, this is not an issue.

Now to your questions:

Is this considered good practice?

That is a matter of opinion. My first intuition says "no", mainly because of the type conversion, but since there are no caveats for your particular use case (i.e. array of boolean), we cannot really have much to criticise about.

Is there any hidden error I might face with this method?

No

Will this method increase readability ?

Yes

There is however at least one alternative that has all the same advantages, but does not rely on some data type conversion:

Alternative: bitset

In case your array is an array of boolean, you can opt to use a numeric data type instead, where each binary bit of a number corresponds to a boolean in the array version.

It is to be expected that this method will be more efficient than the strinfigication option, because that data type conversion obviously takes some time.

Here is a run of the original array pattern:

let arr = [false, false, true];

if (!arr[0] && arr[1] && !arr[2]) console.log("do A");
if (!arr[0] && !arr[1] && arr[2]) console.log("do B");
if (arr[0] && arr[1] && !arr[2]) console.log("do C");

Here is the same logic implemented with a bitset:

let bitset = 0b001;

if (bitset === 0b010) console.log("do A");
if (bitset === 0b001) console.log("do B");
if (bitset === 0b110) console.log("do C");

If ever you need more bits than are available in the number data type (53 bits), then you can go for BigInt. For instance:

let bitset = 0b1010101010101010101010101010101010101010101010101010101n;

// A partial comparison
if ((bitset & 0b100010001n) === 0b100010001n) console.log("do A");

Of course, it is not necessary to use 0b literals; this is just to highlight the correspondence with the array version. You can save some characters by writing numbers in hexadecimal notation (0x) or even plain decimal, although the latter would be more obscure for the reader of your code.

Related