Home > Software design >  How to get mapped values from string?
How to get mapped values from string?

Time:11-27

I have a string like,

const string =
    "DEVICE_SIZE IN ('036','048','060','070') AND DEVICE_VOLTAGE IN ('1','3') AND NOT DEVICE_DISCHARGE_AIR IN ('S') AND NOT DEVICE_REFRIGERANT_CIRCUIT IN ('H','C')";

From this, I need to map the respective key and value like, DEVICE_SIZE: ["036", "048", "060", "070"]

Current Result:

  const string =
    "DEVICE_SIZE IN ('036','048','060','070') AND DEVICE_VOLTAGE IN ('1','3') AND NOT DEVICE_DISCHARGE_AIR IN ('S') AND NOT DEVICE_REFRIGERANT_CIRCUIT IN ('H','C')";

  const res = string.split('IN ');

  const regExp = /\(([^)] )\)/;

  const Y = 'AND';

  const data = res.map((item) => {
    if (regExp.exec(item)) {
      return {
        [item.slice(item.indexOf(Y)   Y.length)]: regExp.exec(item)[1],
      };
    }
  });

  console.log('data ', data);

Expected Result:

[
  { "DEVICE_SIZE": ["036", "048", "060", "070"] },
  { "DEVICE_VOLTAGE": ["1", "3"] },
  { "NOT DEVICE_DISCHARGE_AIR": ["s"] },
  { "NOT DEVICE_REFRIGERANT_CIRCUIT": ["H", "C"] },
];

I couldn't get the exact result based on my try in the current result. Could you please kindly help me to achieve the above given expected result?

Note: I am trying the above to achieve the end result mentioned in my previous question How to get valid object from the string matching respective array?

CodePudding user response:

You could make use of a single regex with 2 capture groups to match the key and the value.

((?:\bNOT\s )?\w )\s IN\s \('([^()]*)'\)

See the regex demo.

The pattern matches:

  • ( Capture group 1
    • (?:\bNOT\s )? Optionally match the word NOT followed by 1 whitespace chars
    • \w Match 1 or more word characters
  • ) Close group
  • \s IN\s Match the word IN between whitespace characters
  • \(' Match ('
  • ([^()]*) Capture group 2, match 1 occurrences of any char except ( and )
  • '\) Match ')

To create the dynamic keys for the object, you can make use of Object Initializer and you can split on ',' to create the resulting array for the value.

const regex = /((?:\bNOT\s )?\w )\s IN\s \('([^()]*)'\)/g;
const string = "DEVICE_SIZE IN ('036','048','060','070') AND DEVICE_VOLTAGE IN ('1','3') AND NOT DEVICE_DISCHARGE_AIR IN ('S') AND NOT DEVICE_REFRIGERANT_CIRCUIT IN ('H','C')";
const data = Array.from(
  string.matchAll(regex), m =>
  ({
    [m[1]]: m[2].split("','")
  })
);
console.log(data);

CodePudding user response:

You could have split by AND first and then split again with IN to separate the key and the value part.

This would also work:

const string =
  "DEVICE_SIZE IN ('036','048','060','070') AND DEVICE_VOLTAGE IN ('1','3') AND NOT DEVICE_DISCHARGE_AIR IN ('S') AND NOT DEVICE_REFRIGERANT_CIRCUIT IN ('H','C')";

const output = string
  .split("AND")
  .map((item) => item.split("IN").map((text) => text.trim()))
  .map(([key, value]) => ({
    [key]: value.replace(/[\(\)\']/g, "").split(","),
  }));

console.log(output);

CodePudding user response:

You can use Object.fromEntries, which transforms key-value tuples [string, any] into an object with those tuples:

const data = Object.fromEntries(res.map((item) => {
    if (regExp.exec(item)) {
      return [item.slice(item.indexOf(Y)   Y.length).trim(), regExp.exec(item)[1].split(',').map(value => value.slice(1, -1))];
    }
    return undefined;
}).filter(Boolean));

and then continue from there.

  • Related