1

我正在使用 array.sort 对对象数组进行排序。

除了自己进行比较之外,有没有办法确定这些对象的顺序是否发生了变化?一些内置的 JS 功能?我不需要知道更改的数量,只需知道至少有 1 个更改。

更新:

我正在对自定义对象进行排序,例如:

[
 { 'value' : 5, 'name' : 'foo'},
 { 'value' : 3, 'name' : 'bar'},
 { 'value' : 10, 'name' : 'js'}
]

更新 2:

我正在考虑在生成对象时添加一个额外的自定义属性“order”,然后在.sort 之后检查“order”是否是连续的。有更快/更好的方法吗?

4

8 回答 8

3

没有任何内置功能可以满足您的要求。如果它是一个简单的数组,您可以使用 join/toString() 并比较两个最终字符串。如果数组包含对象,可能会使用 JSON.stringify 并进行比较。

var myArray1 = [1,2,3,4,5],
    myArray2 = [2,1,3,4,5],
    myArray1_sorted = myArray1.slice().sort(),
    myArray2_sorted = myArray2.slice().sort();

//Check to see if the strings are the same or different
console.log( myArray1_sorted.toString() === myArray1.toString() ); //true - sort should not change anything
console.log( myArray2_sorted.toString() === myArray2.toString() ); //false - sort should have changed order
于 2012-05-17T20:16:19.957 回答
1

来自Array.sort文档:

array.sort([compareFunction])

所以很明显,没有内置的解决方案/方法来检测至少一个元素在排序过程中是否改变了它的位置。所以你需要编写自己的方法:

function isAnyElementChangedItsPosition( unsortedArray, sortedArray ){
   for( var i = 0; i < unsortedArray.length; ++i){
       if( unsortedArray[i] !== sortedArray[i] ){
           return true;
       }
   } 
   return false;
}
于 2012-05-17T20:18:04.253 回答
1

如果您不想弄乱数组的两个副本,请在开始排序之前检查数组。

您可以遍历数组并在每个项目都处于其排序位置时返回 true(比较“小于”下一个项目)或在检测到一个项目位于错误位置时返回 false。

由于您使用的是对象,因此比较代码取决于您对对象进行排序的方式。

于 2012-05-17T20:41:16.557 回答
0

您必须以某种方式比较数组。您可以轻松克隆数组并进行检查:

  var arr = [5, 4, 1, 6]
  var arrBefore = arr.slice(0);
  arr.sort()

  for(var i =0; i< arr.length; i++) { 
    if (arrBefore[i] !== arr[i]) {
      // a change was made
    }
  } 
于 2012-05-17T20:16:08.987 回答
0

简而言之:没有内置函数,你必须检查是否相等。

这是检查相等性的一种方法:

function arraysEqual(a, b) {

    // Are the lengths the same?
    var i = a.length;
    if (i !== b.length)
        return false;

    // Are all the values the same?
    while (i --) {
        if (a[i] !== b[i])
            return false;
    }

}

请注意,这不会检查它们是否是数组;arraysEqual("abc", ["a", "b", "c"])是真的。如果需要,您可以添加此检查。

于 2012-05-17T20:17:41.603 回答
0

没有内置功能可以做你想做的事。

这个怎么样:

function isArraySorted(array) {
    if (!array.length) {
        return true;
    }
    var lastElement = array[0];
    for (var i = 1; i < array.length; i++) {
        if (array[i] <= lastElement) {
            return false;
        }
        lastElement = array[i];
    }
    return true;
}

alert(isArraySorted([1,2,3]) + " " + isArraySorted([1,2,3,2.5]));

var array = [1,2,3];

if (!isArraySorted(array)) {
    // No need to do the sort if the array is already sorted.
    array.sort();
}
于 2012-05-17T20:17:50.840 回答
0

不复制数据,因为字符串和并行数组会这样做。

function chkOrder(a) {
  for(var i =1; i< a.length; i++)
    if (a[i-1] > a[i]) return false;
  return true;
}

如果您颠倒顺序,您可能需要处理 th ">" 符号,这也将在第一次出现时返回 false(未排序)

如果我们可以控制包含的对象,那么我们就可以控制对象的变化并触发父排序

function O(parent,data) {//initialize with parent and value array/object
  this.parent=parent;
  this.data=data;
  //shortcurt to sort parent
  this.sort=function()
    {console.log("sortingparent");this.parent.sort(this.parent.sortfunc);}
  this.setData=function(data) {
  this.data=data;
  this.sort();
}
//if changes can be groupped then is more efficient to signal parent dirty and sort latter
this.setKey=function(key,value) {//change value in the data
  if (key==parent.sortkey&&value!=this.data[key]) {
    this.data[key]=value;
    this.sort();
  } else this.data[key]=value;
}
this.parent.push(this);
  this.sort();
  return this;
}
//-------
//using a simple array, this could also be and object and have specific func's
var arr=[];
//example, sort by name, ascending
arr.sortkey="name";
//closure to build a sort predicate bound to the used key
function setkey(key) {return function(a,b) {return a.data[key]>b.data[key];}}
arr.sortfunc=setkey(arr.sortkey);
var b=new O(arr,{name:"B",value:0});
var c=new O(arr,{name:"C",value:2});
var a=new O(arr,{name:"A",value:1});
var d=new O(arr,{name:"D",value:3});
console.log("changing value");
a.setKey("value",100);//when not sorting by value its the same as a.data.value=100
console.log("changing name");
a.setKey("name","X");//this will fire parent sort
for(n=0;n<arr.length;n++) console.log(arr[n].data.name,"=",arr[n].data.value);
于 2012-05-17T20:28:25.670 回答
-1
var data = [
    { 'value' : 5, 'name' : 'foo'},
    { 'value' : 3, 'name' : 'bar'},
    { 'value' : 10, 'name' : 'js'}
];

var changed = sortAndReport(data, byValue);

// sortAndReport :: [a], (a, a -> Number) -> Boolean
// Sorts an array according to the provided Array.prototype.sort
// compare function and returns a Boolean indicating whether
// sorting changed the order of the array.
function sortAndReport(a, fn) {
    var changed = false;

    a.sort(function (a, b) {
        var sortResult = fn(a, b);
        changed        = sortResult > 0;
        return sortResult;
    });

    return changed;
}

// byValue :: { value :: Number }, { value :: Number } -> Number
function byValue(a, b) {
    return a.value - b.value;
}
于 2012-05-17T20:11:16.550 回答