1

我有一系列这种格式的邮政编码(各个国家的):

["100-1001","102-1000","102-1001","102-1002","100-1002","111","112","102-1003","113"]

我需要以以下输出格式从这些数字中推断出范围:

[[upper1,lower1],[upper2,lower2]]

对于上面的示例,这将是:

[["100-1001","100-1002"]["102-1000","102-1003"]["111","113"]]

有没有比将所有内容转换为平面数字、删除分隔符、推断其范围然后重新添加分隔符更好的方法?

目前我对非连字符的邮政编码有这个逻辑 -

getRanges(zipCodes) {
  zipCodes.sort();
  let length = 1;
  let ranges = [];
  for (let i = 1; i <= zipCodes.length; i++) {
    if (i == zipCodes.length || zipCodes[i] - zipCodes[i - 1] != 1) {
      if (length == 1) {
        let upper = lower = zipCodes[i - length];
        ranges.push({lower, upper});
      }
      else {
        let lower = zipCodes[i - length];
        let upper = zipCodes[i - 1];
        ranges.push({lower, upper});
      }
      length = 1;
    }
    else {
      length++;
    }
  }
  return ranges;
}

但是我觉得如果有更好的解析范围的方法,可以避免删除和重新添加分隔符的额外开销。提前致谢

4

2 回答 2

3

一个简单的解决方案是将输入转换为number,string对列表,根据数字进行排序/分类,最后从结果中提取字符串:

function getRanges(arr) {
    let pairs = arr.map(s => [
        Number(s.replace(/\D+/g, '')),
        s
    ])

    pairs.sort((a, b) => a[0] - b[0])

    let ranges = [], last = null

    for (let p of pairs) {
        if (last && last[1][0] === p[0] - 1)
            last[1] = p
        else
            ranges.push(last = [p, p])
    }

    return ranges.map(r => [r[0][1], r[1][1]])
}

const zipCodes = [
    "100-1000",
    "100-1001",
    "100-1002",
    "100-1003",

    "100-1005",

    "200-1000",
    "200-1001",
    "200-1002",

    "200-1006",

    "111",
    "112",

    "114",
    "115",
    "116",
]

console.log(getRanges(zipCodes))

于 2021-09-24T23:08:19.337 回答
2

sort 函数也可以处理字符串。因此,在不删除-this 的情况下,将对邮政编码数组进行排序并成对分组:

function getRanges(zipCodes) {
  zipCodes.sort();
  let ranges = [];
  for (let i = 0; i <= zipCodes.length - 1; i += 2) {
    if (zipCodes[i + 1]) {
      let lower = zipCodes[i];
      let upper = zipCodes[i + 1];
      ranges.push({lower, upper});
    } else {
      let upper = lower = zipCodes[i];
      ranges.push({lower, upper});
    }

  }
  return ranges;
}
const zipCodes = ["100-1001", "102-1000", "102-1001", "102-1002", "100-1002", "111", "112", "113"];
const result = getRanges(zipCodes);
console.log(result);

更新: 此代码不能解决 OP 要求,但有几个人支持它,因为它对邮政编码进行排序和分组。(我认为包括我在内的几个人误解了分组应该如何进行)。

正确的方法是乔治的答案,我想到的唯一改进是在执行实际操作之前进行排序,map因此它返回与原始请求相同的顺序。否则我想不出更好的实现,所以如果有人发现它有用,我会留下我的原始代码。

于 2021-09-24T22:42:37.730 回答