重新排序javascript数组

时间:2015-01-30 14:10:56

标签: javascript arrays

所以我有这些数据:

var data = [
      [
       {name:"John", age:32, x:false}, 
       {name:"Mark", age:44, x:false}, 
       {name:"John", age:21, x:true}
      ],

      [
       {name:"John", age:65, x:false}, 
       {name:"Mark", age:77, x:false}, 
       {name:"John", age:78, x:true}
      ],

      [
       {name:"John", age:11, x:false}, 
       {name:"Mark", age:15, x:false}, 
       {name:"John", age:65, x:true}
      ]
    ];

我想要做的是重新排列这些数据,以便包含x = true的对象位于第一个位置[0]。这应该是这样的:

var data = [
      [
       {name:"John", age:21, x:true},
       {name:"John", age:32, x:false}, 
       {name:"Mark", age:44, x:false}

      ],

      [
       {name:"John", age:78, x:true},
       {name:"John", age:65, x:false}, 
       {name:"Mark", age:77, x:false} 

      ],

      [
       {name:"John", age:78, x:true},
       {name:"John", age:11, x:false}, 
       {name:"Mark", age:15, x:false}, 
      ]
    ];

任何帮助?

2 个答案:

答案 0 :(得分:2)

首先创建一个compare()函数:

function compare(a,b) {
  if (b.x) return 1;
  if (a.x) return -1;
  return 0;
}

然后使用这个逻辑对每个数组进行排序:

for(var i=0,l=data.length; i<l; i++) data[i].sort(compare);

JS Fiddle demo

修改

ScottSauyet指出此方法不保持相同值之间的原始顺序。所以我采取了不同的方法,因为我们并没有真正对值进行排序,而是将它们分开。

看起来像这样:

Array.prototype.booleanSortBy = function(property){
    var res = {true : [], false: []};
    for(var i=0, l=this.length; i<l; i++){
        res[ this[i][property] ].push( this[i] );
    }
    return res[true].concat( res[false] );
}

Check it out in JS Fiddle

注意:如果要在现实世界中使用它,则需要进行属性检查。如果传递给此函数有问题,它将fail miserably

答案 1 :(得分:1)

blex 的答案几近完美。但是如果你经常这样做,为了对不同的布尔字段进行排序,你可能想要使用更高阶函数将它提升到一个级别:

function compareOn(name) {
  return function compare(a,b) {
    if (b[name]) return 1;
    if (a[name]) return -1;
    return 0;
  };
}

var comparator = compareOn('x');

for(var i=0,l=data.length; i<l; i++) data[i].sort(comparator);

更新

blex asked我对上述算法的意义并没有产生稳定的排序。这是为了清除这一点。稳定排序是指按排序标准认为相同的两个值与原始列表中的排序顺序相同的排序。虽然这不是规范的要求,但只要排序回调遵循规则,Javascript引擎通常具有稳定的排序。 (Chrome一直是个例外。)

排序功能应该有certain behavior。它应该接受两个值并返回

  • 如果第一个值小于第二个
  • ,则为负数
  • 如果第一个值大于第二个
  • ,则为正数
  • 如果两个值相等则为零

这个排序功能:

function (a,b) {
    if (b.x) return 1;
    if (a.x) return -1;
    return 0;
};

实际上并没有这样做,因此即使在稳定的排序环境中,例如Firefox,它也会返回一些令人惊讶的结果。它不符合条件,因为如果两个值均为x: true,则此函数返回1而不是必需的0

              Expected                        Actual
                 b.x                            b.x
             true   false                   true   false
          +-------+-------+              +-------+-------+
     true |   0   |  -1   |         true |   1   |  -1   |
a.x       +-------+-------+    a.x       +-------+-------+
    false |   1   |   0   |        false |   1   |   0   |
          +-------+-------+              +-------+-------+

这种情况的根本原因在于,实际大于或小于案件没有任何破坏;那些仍然是正确的。麻烦的是,应该平等的情况不会报告。但这只意味着排序会将应该相等的内容放入可能不寻常的顺序中。并且根据排序算法,它可能以不可预测的方式这样做。

避免这些问题的此功能的未经测试的变体可能如下所示:

function (a,b) {
    if (b.x) {
        if (a.x) return 0;
        return 1;
    }
    if (a.x) return -1;
    return 0;
};