Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript排序函数错误地更改元素';阵列中的位置_Javascript_Arrays_Sorting - Fatal编程技术网

Javascript排序函数错误地更改元素';阵列中的位置

Javascript排序函数错误地更改元素';阵列中的位置,javascript,arrays,sorting,Javascript,Arrays,Sorting,我在AngularJS应用程序中使用数组排序功能。它使用变量direction,来确定是以升序(direction===-1)还是降序(direction===1)的方式对数据进行排序 出了什么问题:有时,当我进行排序时,数组中应该位于同一位置的元素会返回到不同的位置,而数组中没有任何实际更改 例如,如果我有: var arr = [ {id: 3, name: 'd'}, {id: 2, name: 'b'}, {id: 1, name: 'a'

我在AngularJS应用程序中使用数组排序功能。它使用变量
direction
,来确定是以升序(
direction===-1
)还是降序(
direction===1
)的方式对数据进行排序

出了什么问题:有时,当我进行排序时,数组中应该位于同一位置的元素会返回到不同的位置,而数组中没有任何实际更改

例如,如果我有:

   var arr = [
       {id: 3, name: 'd'},
       {id: 2, name: 'b'},
       {id: 1, name: 'a'},
       {id: 2, name: 'c'}
   ];
我按“id”排序,方向为
-1
,返回的名称如您所料为“a,b,c,d”。然后我将再次排序(将方向更改为
1
),它将反转方向。但是如果我再次对它排序(使用
方向==-1
),它将返回“a,c,b,d”的顺序

这是一个简化的例子;事实上,这远比这不可预测

我有一种感觉,在我的分类中,我没有正确地使用
方向。见下文:

this.sortData = function (data, type, direction) {

    return data.sort(sortFunct);

    function sortFunct(a, b) {
        var numberTypes = ['Thread', 'Job', 'FolderCount', 'MessageCount', 'EmailCount', 'CalendarCount', 'TaskCount', 'OtherCount', 'JobId', 'BatchId', 'ItemsTotal', 'ItemsRemaining', 'ItemsFailed', 'Size', 'progress', 'PercentComplete'];
        var stringTypes = ['Level', 'StatusMessage', 'Author', 'ItemStatus', 'JobStatus', 'SourceMailbox', 'TargetMailbox', 'Subject', 'Folder', 'MessageClass', 'StatusMessage', 'Path', 'Owner1',];

        if (numberTypes.indexOf(type) !== -1) {
            return direction * (a[type] - b[type]);
        } else if (stringTypes.indexOf(type) !== -1) {
            if (!a[type]) {
                return 1;
            } else if (!b[type]) {
                return -1;
            } else {
                return a[type].localeCompare(b[type]) * direction;
            }
        } else if (type === 'DiscoveryDate' || type === 'ReceivedDate' || type === 'Timestamp') {
            if (a[type] > b[type]) {
                return direction * 1;
            } else if (a[type] < b[type]) {
                return direction * -1;
            } else {
                return 0;
            }
        } else {
            return direction * (a[type] - b[type]);
        }
    } // End sortFunct
};
this.sortData=函数(数据、类型、方向){
返回data.sort(sortFunct);
函数排序功能(a,b){
var numberTypes=['Thread','Job','FolderCount','MessageCount','EmailCount','CalendarCount','TaskCount','OtherCount','JobId','BatchId','ItemsTotal','ItemsRemaining','ItemsFailed','Size','progress','PercentComplete'];
var stringTypes=['Level','StatusMessage','Author','ItemStatus','JobStatus','SourceMailbox','TargetMailbox','Subject','Folder','MessageClass','StatusMessage','Path','Owner1',];
if(numberTypes.indexOf(type)!=-1){
返回方向*(a[类型]-b[类型];
}else if(stringTypes.indexOf(type)!=-1){
如果(!a[type]){
返回1;
}如果(!b[类型]),则为else{
返回-1;
}否则{
返回a[type].localeCompare(b[type])*方向;
}
}else if(type=='DiscoveryDate'| | type=='ReceivedDate'| | type=='Timestamp'){
如果(a[type]>b[type]){
返回方向*1;
}如果(a[type]
ECMAScript不要求排序稳定()。此外,即使排序是稳定的,也不能期望代码知道何时应该反转相同的记录(2和2),何时不应该反转。为了能够做到这一点,您不能从比较器返回
0
——也就是说,在平局的情况下,您需要一个辅助键来帮助消除顺序的歧义。如果想不出更好的方法,可以给每个对象排序。

“sort()方法对数组中的元素进行排序并返回数组。排序不一定是稳定的。”

见:

而且:


“HTH,

用于
.sort()
的ECMAScript规范不要求它是稳定的,因此自定义排序函数所说的相同元素(例如,返回值
0
)彼此之间的顺序将没有保证,事实上,它们最终的顺序可能会受到排序之前的顺序的影响

如果您想要一致的排序,那么您永远不需要从自定义排序函数返回
0
,除非这两个项完全相同,您永远无法分辨哪个是哪个

当主键相同时,需要测试一个辅助键并返回比较结果。如果二级密钥相同,则比较三级密钥,以此类推,直到您认为值得使用为止

这种二次比较可以使排序保持稳定,这样无论您以前使用的是什么顺序,排序都将始终以可预测的顺序进行


我还看到过一些排序方案,它们创建一个唯一的键并将其分配给每个对象,并将其用作第二个或第三个键,从而确保如果您关心的键是相同的,那么您可以比较唯一的键并始终具有一致的稳定排序


下面是一个方案示例,如果比较字段(本例中的年龄具有相同的值)保持原始顺序。为了知道原始顺序是什么,它使用标识原始顺序的
origOrder
属性标记每个对象

var数据=[
{姓名:“艾米”,年龄:13},
{姓名:“安妮”,年龄:13},
{姓名:“约翰”,年龄:11},
{姓名:“杰克”,年龄:12},
{姓名:“Ted”,年龄:11},
{姓名:“爱丽丝”,年龄:12}
];
//按原始顺序标记每个对象
data.forEach(函数(项、索引){
item.origOrder=索引;
});  
数据排序(函数(a,b){
var diff=a.年龄-b.年龄;
如果(差异!==0){
返回差;
}否则{
返回a.origOrder-b.origOrder;
}
});  
//在代码段中显示结果

document.write(JSON.stringify(data))有趣,我不知道要在这里搜索的正确术语。您认为返回
a
b
的原始索引,然后通过辅助键与之进行比较,会使排序更稳定吗?不确定“返回原始索引”是什么意思?从何处返回?我的意思是,拥有一个真正独特的领域是一件大事;如果这是未修改的数组索引,那很好,但必须事先将其放在对象上,以便比较器可以访问它。我确实有一个唯一的ID字段,但我看不出在该字段上进行比较会如何影响数组排序的稳定性。我的意思是数组中元素的原始索引;如果比较结果为===0,且a在数组中的原始索引低于b,则返回1,否则返回-1。在另一个an的注释中询问此问题