使用AlphaNumeric对对象数组进行排序

时间:2018-01-08 13:32:20

标签: javascript sorting ecmascript-6

我有一个带有混合字母数字的Object数组。我需要按大小排序。

var data = [
{size: "40 SHORT", avail: true},
{size: "46 LONG", avail: true},
{size: "42 SHORT", avail: true},
{size: "40 REG", avail: true},
{size: "42 LONG", avail: true},
{size: "42 REG", avail: true},
{size: "44 REG", avail: true},
{size: "44 LONG", avail: true},
{size: "46 REG", avail: true},
{size: "48 REG", avail: true},
{size: "44 SHORT", avail: true},
{size: "38 REG", avail: true},
{size: "40 LONG", avail: true},
{size: "48 LONG", avail: true},
{size: "38 SHORT", avail: true}
]

我需要像这样的输出。

var Output = [
{size: "38 SHORT", avail: true},
{size: "40 SHORT", avail: true},
{size: "42 SHORT", avail: true},
{size: "44 SHORT", avail: true},
{size: "38 REG", avail: true},
{size: "40 REG", avail: true},
{size: "42 REG", avail: true},
{size: "44 REG", avail: true},
{size: "46 REG", avail: true},
{size: "48 REG", avail: true},
{size: "40 LONG", avail: true},
{size: "42 LONG", avail: true},
{size: "44 LONG", avail: true},
{size: "46 LONG", avail: true},
{size: "48 LONG", avail: true}
]

3 个答案:

答案 0 :(得分:0)

您需要做的是对字符串进行排序,但作为两个不同的属性。因此,如果你可以在适当的位置创建一个新的排序数组,我会将数组映射到一个包含原始数据的对象数组,另一个属性包含在空格字符上拆分字符串的结果。

然后您需要做的就是首先查看SHORT/REG/LOG是否匹配,如果是,请对数字进行排序,否则按照为这些单词定义的顺序排序。

var data = [{size: "40 SHORT", avail: true},{size: "46 LONG", avail: true},{size: "42 SHORT", avail: true},{size: "40 REG", avail: true},{size: "42 LONG", avail: true},{size: "42 REG", avail: true},{size: "44 REG", avail: true},{size: "44 LONG", avail: true},{size: "46 REG", avail: true},{size: "48 REG", avail: true},{size: "44 SHORT", avail: true},{size: "38 REG", avail: true},{size: "40 LONG", avail: true},{size: "48 LONG", avail: true},{size: "38 SHORT", avail: true}];

data = data
  .map(o => ({orig: o, p: o.size.split(' ')}))
  .sort((a, b) => 
    a.p[1] === b.p[1] ? a.p[0] - b.p[0] :
    a.p[1] === "SHORT" || (a.p[1] === "REG" && b.p[1] === "LONG") ? -1 :
    1)
  .map(o => o.orig);

console.log(data);

您也可以进行就地排序。我们只需要将结果复制到原始数组中。

无论哪种方式,这里的好处是我们不会在.sort()回调内的每次迭代中进行字符串拆分和对象创建,这在计算和内存消耗方面会不必要地花费。

这个甚至更清洁,更快。它利用了单词固有的反向字母顺序。它使用排序中每个单词的第一个字母的否定字符代码,因此它完全是数字排序。

var data = [{size: "40 SHORT", avail: true},{size: "46 LONG", avail: true},{size: "42 SHORT", avail: true},{size: "40 REG", avail: true},{size: "42 LONG", avail: true},{size: "42 REG", avail: true},{size: "44 REG", avail: true},{size: "44 LONG", avail: true},{size: "46 REG", avail: true},{size: "48 REG", avail: true},{size: "44 SHORT", avail: true},{size: "38 REG", avail: true},{size: "40 LONG", avail: true},{size: "48 LONG", avail: true},{size: "38 SHORT", avail: true}];

data = data
  .map(o => {
    let [n,t]=o.size.split(' ');
    return {orig:o, n:+n, t:-t.charCodeAt()}
  })
  .sort((a, b) => a.t - b.t || a.n - b.n)
  .map(o => o.orig);

console.log(data);

答案 1 :(得分:0)

这是我的尝试。它不是通用的,但它的想法是分离" size"的字面部分。来自" size"的数字部分并进行顺序比较。

function compare(a, b) {
  // obvious equality case, just to skip unnecessary calculations
  if(a.size === b.size) {
    return 0;
  }
  // literal comparison: SHORT < REG < LONG
  var aL = a.size.replace(/^[\s\d]+/, ''), bL = b.size.replace(/^[\s\d]+/, '');
  if((aL == 'SHORT' && bL != 'SHORT') || (aL == 'REG' && bL == 'LONG')) {
    return -1;
  }
  if((aL == 'REG' && bL == 'SHORT') || (aL == 'LONG' && bL != 'LONG')) {
    return 1;
  }
  // numeric comparison: 38 < 40 < 44 etc
  var aN = parseInt(a.size, 10), bN = parseInt(b.size, 10);
  if (aN < bN) {
    return -1;
  }
  if (aN > bN) {
    return 1;
  }
  return 0;
}

console.log(data.sort(compare));

答案 2 :(得分:-1)

您可以拆分该值并获取给定大小的数值。

&#13;
&#13;
var data = [{ size: "40 SHORT", avail: true }, { size: "46 LONG", avail: true }, { size: "42 SHORT", avail: true }, { size: "40 REG", avail: true }, { size: "42 LONG", avail: true }, { size: "42 REG", avail: true }, { size: "44 REG", avail: true }, { size: "44 LONG", avail: true }, { size: "46 REG", avail: true }, { size: "48 REG", avail: true }, { size: "44 SHORT", avail: true }, { size: "38 REG", avail: true }, { size: "40 LONG", avail: true }, { size: "48 LONG", avail: true }, { size: "38 SHORT", avail: true }];

data.sort(function (a, b) {
    function getParts(o) {
        var array = o.size.split(' ');
        return { value: array[0], size: { SHORT: 1, REG: 2, LONG: 3 }[array[1]] };
    }
    
    var aa = getParts(a),
        bb = getParts(b);
        
    return aa.size - bb.size || aa.value - bb.value;
});

console.log(data)
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;