0

I need to find key of "1"s in the data below based on each bit of binaryInput. I have posted similar question before. But I am stuck on getting exact keys as result.

I have data as below:

item on ->  0
item off -> 1    

item detected ->  0
item not detected-> 1

item responded->  0
item not responded-> 1

item passed -> 0
item failed -> 1


Example:
lets take binaryInput= '1100'
var reversedInput= binaryInput.split("").reverse(); // '0011'
result =[];

Now first bit of reversedInput which is '0', need to return whether item on or item off. Second bit '0' need to return whether item detected or not detected. Third bit '1'would return item responded or not responded. fourth bit '1' return item passed or failed.

I am expecting the result to be ["item not responded", " item failed"] for binaryInput '1100' (reading from right). As we are adding to the result only that are "1"

Another eg: if binaryInput was '0010' (reading from right), result would be ["item not detected"].

Tried as below but not effective: Tried storing in the below data structure:

const data = {
"item on" :  "0",
"item off" : "1",
"item detected" :  "0",
"item not detected" : "1",
"item responded" :  "0",
"item not responded" : "1",
"item passed" :  "0",
"item failed" : "1",  
}

 function getKeyByValue(object, value) {
    return Object.keys(object).find(key => object[key] === value);
 }

for (var i = 0; i < reversedInput.length; i++) {
  //getKeyByValue will only return 'item on' or 'item off' but not keys of other '0' or '1'. Since values are not unique.
  var status= getKeyByValue(data, reversedInput[i]); 

if (reversedInput[i] === "1") {
        result.push(status);
  }                                 

Thank you.

Sarahrb
  • 407
  • 11
  • 24
  • why don't you convert this into a decimal value between 0 and 16, and store statuses based on that? similarly to the way Unix file permissions work – Esther Sep 19 '22 at 14:42

2 Answers2

2

If order matters you should use an array, not an object. I suggest a 2-dimensional array -- the first dimension is the attribute, the second is the 0/1 value of the attribute.

Then you can use reduce() to loop over reversedInput and conditionally add the corresponding values from attributes to the result array.

const attributes = [
  ["item off", "item on"],
  ["item not detected", "item detected"],
  ["item not responsed", "item responded"],
  ["item failed", "item passed"]
];

let binaryInput = '1100';
let reversedInput = binaryInput.split("").reverse(); // '0011';
let result = reversedInput.reduce((acc, val, i) => val == '1' ? [...acc, attributes[i][val]] : acc, []);
console.log(result);
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • When I give binaryInput as '001000000010', '10010010' or '10010', I get uncaught TypeError: Cannot read properties of undefined (reading '1'). I understand there are only four 0/1 values. May I know how I can handle this in reduce line. Thank you. – Sarahrb Sep 21 '22 at 04:24
  • To get only last four characters of string, I could use if (binaryInput.length > 4) { binaryInput.substr(binaryInput.length - 4)}. Is there a way to handle this directly in reduce . – Sarahrb Sep 21 '22 at 06:39
  • 1
    Change `val == '1'` to `i < attributes.length && val == '1'` – Barmar Sep 21 '22 at 14:51
0

If we're using bits, why not use bitwise operators? In particular the bitwise AND operator:

  0010     0010
& 0011   & 1100
------   ------
  0010     0000

For each bit in the two operands, if they are both 1, then the output bit is 1. We can use this to test if a bit exists (is on) in a number. This is usually called "bit masking".

// map of masks to statuses
const masks = {
    "1000": ["off", "on"],
    "0100": ["not detected", "detected"],
    "0010": ["not responded", "responded"],
    "0001": ["failed", "passed"],
};

// original input (string type)
const input = "1100";

// convert from binary to decimal (now number type)
const reversed = parseInt(input.split("").reverse().join(""), 2);

const result = [];

for (const mask in masks) {
    if (reversed & mask) // if the mask did not produce a 0, then the bit exists
        result.push(masks[mask][+!(reversed & mask)]);
}

console.log(result);

+!(reversed & mask) is just a gimmick to quickly negate the result of the mask, then turn that into a number. Because negating the result gives us a boolean, when we turn that into a number, we get 0 or 1, which conveniently allows us to get the correct status from the map.

kelsny
  • 23,009
  • 3
  • 19
  • 48