3

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 ?

Emre Koc
  • 1,481
  • 10
  • 18
Cerceis
  • 770
  • 3
  • 14
  • 2
    Feels like your original array should have been a bitset to begin with, but that can vary with context. – T Tse Aug 19 '20 at 05:12
  • What ShioT said. You could also try to make it into an object: `{prop1: true, prop2: true,...}`. That way you gain more readability, since you use the keys to check the values. The way you are doing it now, I can imagine it gets confusing quite fast. If you look at that code in some months or even years it will be hard to figure out, why this order does that and another order does something else. – acincognito Aug 19 '20 at 05:36
  • True, using object with naming might be an even better solution than just pure Array. Also stringifying object should produce an even complex unique string that has more readibility – Cerceis Aug 19 '20 at 06:01
  • Are you confident the JSON stringify operation is standardised to the degree that this is reliable, and won't ever change? E.g., might some specific browser stringify the result to `"[false, false, false]"` (with spaces)? It's just as valid a result as far as JSON is concerned, but breaks your code… – deceze Aug 19 '20 at 06:31
  • @deceze There is a possibility, but most likely not gonna happen. JSON.stringify() has an optional "space" parameter to insert whitespace if needed. By default there should be no whitespace added. Or if you are extra paranoid and want to be safe. Just simply add .replace(" ","") just to make sure there is no whitespace at all. – Cerceis Aug 19 '20 at 06:59
  • Does this answer your question? [How to compare arrays in JavaScript?](https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript) – ceving Aug 19 '20 at 07:05
  • We can be confident that the `JSON.stringify` operation is standardised to that degree. See [ECMAScript specification on the topic](https://tc39.es/ecma262/#sec-json.stringify). – trincot Aug 19 '20 at 08:39

3 Answers3

0

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).

Emre Koc
  • 1,481
  • 10
  • 18
0

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');
akop
  • 5,981
  • 6
  • 24
  • 51
0

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.

trincot
  • 317,000
  • 35
  • 244
  • 286