1

I'm attempting to parse a version string (examples below) in order to return a value depending on a key that matches the following rules listed below.

Each version ID can include a wildcard, however the input cannot. Ofcourse this object is dynamic and will most likely include more version matches.

In this example, the version string will be "1.2.3".

  • Version IDs higher than 3.2.1 will return "null"
  • Version IDs between 3.2.1 and 2.8.10 will return "testing_server"
  • Version ID of 2.8.10 will return "second_value"
  • Version IDs between 2.8.10 and 1.0.* will return "last value"
  • Version IDs matching 1.0.* or less (including 0.*) will return "last value"

Example object:

{
   "3.2.1": "testing_server",
   "2.8.10": "second_value",
   "1.0.*": "last value"
}

I have tried several functions each including regex, or manual comparisons but haven't achieved much luck. I know its a bit of a tough one, but hopefully someone can help. :)

mplungjan
  • 169,008
  • 28
  • 173
  • 236
Max
  • 128
  • 5
  • 2
    There is no JSON here. It is a POJO (plain old JavaScript object) - JSON is a string representation of an object – mplungjan Nov 01 '21 at 12:33
  • 1
    `const version = Object.keys(obj).map(key => { const versions = key.split("."); if (...) return "testing_server"; else if (....) return "second value""; return "error" })` ... – mplungjan Nov 01 '21 at 12:35
  • I really don't want to be returning static values, even in this case, because the function needs to be dependant on possible version wildcards, extra numbers, etc. The object won't be the same each time, same with the version string. So it needs to all be dynamic in a way. – Max Nov 01 '21 at 13:32
  • I do not understand your comment. In the question you want to return static values and now not? – mplungjan Nov 01 '21 at 13:33
  • Basically, the object and the values it returns will be different each time, as I have to run this on about 40 different "configs" you could call them. The version string also varies and won't be the same for every time. So it may end up using "3.2.1" as a version string, then next using "2.3.*" as another version string, along with the aligning config which will follow the same structure, just won't include the same values. Hopefully this clears it up better :) – Max Nov 01 '21 at 13:39

3 Answers3

1

Here is a start.

const versions = {
  "4": null,
  "3.2.1": "testing_server",
  "2.8.10": "second_value",
  "1.0.*": "last value"
}

const maxLength = 3
const getLiteral = (versions,version) => {
  return Object.entries(versions).filter(([key,val]) => {
    const parts = key.split(".").map(part => part.padStart(maxLength,"0")).join(".")
    const vparts = version.split(".").map(part => part.padStart(maxLength,"0")).join(".")
    console.log(vparts,parts,vparts > parts)
    return vparts > parts
  }).flat()[1] || null
};


let verText = getLiteral(versions,"1.2.3")
console.log(verText)
verText = getLiteral(versions,"4.2.3")
console.log(verText)
mplungjan
  • 169,008
  • 28
  • 173
  • 236
1

I would use a function like this to make the version string comparable:

function comparableValue(versionString) {
  const digits = versionString.split(".");
  digits.reverse();
  let value = 0;
  for (let i = 0; i < digits.length; i++) {
   value += Math.pow(1000, i) * digits[i];
  }
  return value;
}

function classify(wildcard, value) {
  const boundaries = {
    "3.2.1": "testing_server",
    "2.8.10": "second_value",
  };
  const lowestBoundary = `1.0.${wildcard}`;
  boundaries[lowestBoundary] = "last_value";
  const keys = Object.keys(boundaries);
  keys.sort(function(a, b) {
    return comparableValue(a) - comparableValue(b);
  });
  for (const key of keys) {
    if (comparableValue(value) < comparableValue(key)) {
      return boundaries[key];
    }
  }
  return null;

}

const examples = [
  "3.5.5",
  "3.1.1",
  "2.10.10",
  "2.8.8",
  "1.1.1",
  "0.4.2",
];


const answers = {};

for (const example of examples) {
  answers[example] = classify(3, example);
}

console.log(answers);

convert each 1.1.1 style version into a comparable value by making each digital worth 1000 times as much as the one to the right. Since the numbers will never get up to 1000, it should always work. 800 or 258 would work too, except it makes it harder to debug by printing out the comparable numbers.

Then, if I understand correctly, I would make the sort function take the value of the wildcard as an argument.

Alex028502
  • 3,486
  • 2
  • 23
  • 50
0

I ended up using "compare-versions" along with some logic to get it going.

const compareVersions = require('compare-versions');

function getVersion(version) {
    const versions = {
        "3.2.1": "testing_server",
        "2.8.10": "second_value",
        "1.0.*": "last value"
    }
    const sortedKeys = Object.keys(versions).sort(compareVersions);

    // not required
    //if (compareVersions(version, sortedKeys[sortedKeys.length - 1]) > 0) return null;

    let i = 0;
    while (i < sortedKeys.length && compareVersions(version, sortedKeys[i]) > 0) i++;
    return versions[sortedKeys[i]] || null;
}

const examples = [
    "3.2.2",
    "3.2.1",
    "2.8.11",
    "2.8.10",
    "1.1.0",
    "1.0",
    "0.0"
];

const answers = {};
for (const example of examples) {
    answers[example] = getVersion(example);
}
console.log(answers);
Max
  • 128
  • 5