【问题标题】:Sort an array of strings by two or more substrings in javascript在javascript中按两个或多个子字符串对字符串数组进行排序
【发布时间】:2015-09-03 14:28:27
【问题描述】:

我有一个如下所示的 javascript 数组:

var data =  ["size64_tolPercent0.01_best", "size256_tolPercent0.01_best", "size256_tolPercent0_worst", "sizemax_tolPercent0_worst", "size1518_tolPercent0_worst", "size64_tolPercent0.01_worst", "size512_tolPercent0.01_worst", "size1518_tolPercent0.01_worst", "size256_tolPercent0_best"] etc

我想对这个数组进行排序:

  1. 通过子字符串“best”和“worst”。
  2. 通过 tolPercents 0 和 0.01
  3. sizes (64, 256, 512, 1518, max).. 如果尺寸按字符串排序会很好,因为它包含“max”关键字..

所以,我们最终得到一个如下所示的结果数组:

["size64_tolPercent0_best", "size256_tolPercent0_best", "size512_tolPercent0_best", "size1518_tolPercent0_best", "sizemax_tolPercent0_best", "size64_tolPercent0.01_best", "size512_tolPercent0.01_best", "size1518_tolPercent0.01_best", "size64_tolPercent0_worst", "size256_tolPercent0_worst", "size512_tolPercent0_worst", "size1518_tolPercent0_worst", "sizemax_tolPercent0_worst"] etc

我可以使用其中一种方法对字符串进行排序,但不是全部。

到目前为止,这是我尝试过的,我确定我做错了,只是需要一些正确方向的帮助。现在做 1 和 3:

var someLargeValue = 10000000;
data.sort(function(x,y){
  var xp = x.substr(getPosition(x, '_', 2) + 1, x.split("_").pop().length);
  var yp = y.substr(getPosition(y, '_', 2) + 1, y.split("_").pop().length);
  return xp == yp ? 0 : xp < yp ? -1 : 1;
});
data.sort(function(x,y){
  var xp = x.substr(4, getPosition(x, '_', 1) - 4);
  var yp = y.substr(4, getPosition(y, '_', 1) - 4);
  if(xp === "max") {
    xp = someLargeValue;
  }
  if(yp === "max") {
    yp = someLargeValue;
  }
  xp = parseInt(xp);
  yp = parseInt(yp);

  return xp == yp ? 0 : xp < yp ? -1 : 1;
});
function getPosition(str, m, i) {
    return str.split(m, i).join(m).length;
}

但我担心我正在尝试的代码是按顺序进行排序.. 那么第一个自定义排序方法会被第二个覆盖吗?

非常感谢任何帮助。

【问题讨论】:

标签: javascript arrays sorting


【解决方案1】:

此解决方案采用来自 MDN 的 Sorting with map

首先构建一个映射数组,其中包含用于排序的拆分项。然后按自定义顺序排序。

function (a, b) {
    return a.rating.localeCompare(b.rating) ||
           a.tolPercents - b.tolPercents ||
           a.size - b.size;
}

总共:

var data = [
        "size64_tolPercent0.01_best",
        "size256_tolPercent0.01_best",
        "size256_tolPercent0_worst",
        "sizemax_tolPercent0_worst",
        "size1518_tolPercent0_worst",
        "size64_tolPercent0.01_worst",
        "size512_tolPercent0.01_worst",
        "size1518_tolPercent0.01_worst",
        "size256_tolPercent0_best"
    ],
    result = data.map(function (el, i) {
        var a = /^size(.+)_tolpercent(.+)_(.+)$/i.exec(el);
        return {
            index: i,
            rating: a[3],
            tolPercents: a[2],
            size: a[1] === 'max' ? Number.MAX_VALUE : a[1]
        };
    }).sort(function (a, b) {
        return a.rating.localeCompare(b.rating) || a.tolPercents - b.tolPercents || a.size - b.size;
    }).map(function (el) {
        return data[el.index];
    });

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

【讨论】:

  • 感谢您的回答。如果事先不知道尺寸怎么办?
【解决方案2】:

我会首先拆分字符串,以最大限度地减少比较函数所做的工作量,并使其更具可读性。然后,一旦对数组进行排序,我将重新创建字符串。不过使用地图更聪明:https://stackoverflow.com/a/32379540/1636522 :-D

var data = ["size64_tolPercent0_best", "size256_tolPercent0_best", "size512_tolPercent0_best", "size1518_tolPercent0_best", "sizemax_tolPercent0_best", "size64_tolPercent0.01_best", "size512_tolPercent0.01_best", "size1518_tolPercent0.01_best", "size64_tolPercent0_worst", "size256_tolPercent0_worst", "size512_tolPercent0_worst", "size1518_tolPercent0_worst", "sizemax_tolPercent0_worst"];

// split the strings

var re = /max|\d+(?:\.\d+)?(?=_)|[^_]+$/g;

data = data.map(function (x) {
  x = x.match(re); // example: ["64", "0.01", "best"]
  if (x[0] !== 'max') x[0] = parseInt(x[0], 10);
  x[1] = parseFloat(x[1]);
  return x;
});

// sort the array

data.sort(function cmp (a, b) {
  // 1. "best" and "worst"
  if (a[2] > b[2]) return 1;
  if (a[2] < b[2]) return -1;
  // 2. percent
  if (a[1] > b[1]) return 1;
  if (a[1] < b[1]) return -1;
  // 3. size
  if (a[0] === 'max') return 1;
  if (b[0] === 'max') return -1;
  if (a[0] > b[0]) return 1;
  if (a[0] < b[0]) return -1;
  // 4. no differences
  return 0;
});

// recreate the strings

data = data.map(function (x) {
  x[0] = 'size' + x[0];
  x[1] = 'tolPercent' + x[1];
  return x.join('_');
});

// print the result

data.forEach(function (x) {
  document.write(x + '<br />');
});
* {font-family:Courier}

【讨论】:

    【解决方案3】:

    Array类有排序功能:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

    利用compare 参数:

    data.sort(function(a, b) { // Follow the docs as per how a relates to b, returning -1 (a < b),0 (equal) or 1 (a > b) });

    在函数中按要求提取并比较子字符串。

    更新
    阅读您添加的代码后,不要调用 sort() 两次,只需将所有比较合并到同一个排序比较中即可。在第一个不等式处停止 (aValue !== bValue) 并返回该比较。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-14
      • 2014-01-05
      • 2020-04-13
      • 1970-01-01
      • 2014-07-10
      • 2016-05-25
      • 2016-08-15
      • 1970-01-01
      相关资源
      最近更新 更多