将版本号字符串解析为关联值

Parsing a version number string to an associating value

我正在尝试解析版本字符串(下面的示例),以便 return 一个值取决于与下面列出的以下规则匹配的键。

每个版本 ID 都可以包含一个通配符,但输入不能。当然这个对象是动态的并且很可能包含更多版本匹配。

在此示例中,版本字符串将为“1.2.3”。

示例对象:

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

我尝试了几个函数,每个函数都包括正则表达式或手动比较,但没有取得太大的成功。我知道这有点困难,但希望有人能提供帮助。 :)

这是一个开始。

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)

我会使用这样的函数来使版本字符串具有可比性:

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

将每个 1.1.1 样式版本转换为可比值,使每个数字的价值为右侧数字的 1000 倍。由于数字永远不会达到 1000,因此它应该始终有效。 800 或 258 也可以,只是打印出可比较的数字会使调试变得更加困难。

然后,如果我没理解错的话,我会让排序函数将通配符的值作为参数。

我最终使用“compare-versions”以及一些逻辑来实现它。

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