更新 2
我在排序函数中添加了权重查找,将性能和稳定性提高了大约 100%,因为之前的排序函数没有考虑所有类型,1 == "1"
结果取决于数组的初始顺序,如@Esailija 指出。
这个问题的目的是改进我的这个答案,我喜欢这个问题,因为它被接受了,我觉得有一些性能可以挤出排序功能。我在这里问了这个问题,因为我没有太多线索可以从哪里开始。
也许这也让事情变得更清楚
更新
我改写了完整的问题,因为很多人说我不够具体,我尽力说明我的意思。另外,我重写了sort
函数以更好地表达问题的意图。
设arrayPrev为Array ( A ) ,其中A由 0 到 n 个Element s' ( E )
- 让一个元素要么是
- 原始类型
_
- boolean , string , number , undefined , null
- 对Object O的引用,其中O .type = [object Object]和O可以由
- 0 到 n属性 P,其中P定义为Element plus
- 对O中任何P的循环引用
- 其中任何O可以包含 1 到 n 次。在GetReferencedName(E1) === GetReferencedName(E2)的意义上...
- 0 到 n属性 P,其中P定义为Element plus
- a对O的引用,其中O .type = [object Array]和O的定义类似于A
- 对A中任何E的循环引用
- 原始类型
_
- 让一个元素要么是
- 令 arrayCurr为与arrayPrev长度相同的Array
如下例所示
var x = {
a:"A Property",
x:"24th Property",
obj: {
a: "A Property"
},
prim : 1,
}
x.obj.circ = x;
var y = {
a:"A Property",
x:"24th Property",
obj: {
a: "A Property"
},
prim : 1,
}
y.obj.circ = y;
var z = {};
var a = [x,x,x,null,undefined,1,y,"2",x,z]
var b = [z,x,x,y,undefined,1,null,"2",x,x]
console.log (sort(a),sort(b,a))
问题是,如何有效地对Array B进行排序,以便对 Object 的任何引用或 Primitive 的值,通过相同的compareFunction, sorted, Array A共享与以前完全相同的位置。
就像上面的例子
结果数组应符合规则的地方。
- 让arrayPrev包含Element s'
a
和arrayCurr包含Element s'b
- 让arrayPrev按CompareFunction C排序。
- 让arrayCurr按相同的C排序。
- 让对arrayCur排序的结果是这样的,当在位置n访问arrayCur中的E时,让n例如为 5
- 如果E的类型是Object GetReferencedName(arrayCurr[n]) === GetReferencedName(arrayPrev[n])
- 如果E的类型是Primitive GetValue(arrayCurr[n]) === GetValue(arrayPrev[n])
- 即
b[n] === a[n]
例如b[5] === a[5]
- 这意味着所有元素都应按类型分组,并按值排序。
- 在C中对函数 F的任何调用至少应在 ES5 之前实现,这样就可以在不需要任何 shim 的情况下提供兼容性。
- 让对arrayCur排序的结果是这样的,当在位置n访问arrayCur中的E时,让n例如为 5
我目前的方法是在 arrayPrev 中标记对象,以便在arrayCurr中对它们进行相应的排序,然后再次删除标记。但这似乎没有那么有效。这是当前sort
使用的函数。
function sort3 (curr,prev) {
var weight = {
"[object Undefined]":6,
"[object Object]":5,
"[object Null]":4,
"[object String]":3,
"[object Number]":2,
"[object Boolean]":1
}
if (prev) { //mark the objects
for (var i = prev.length,j,t;i>0;i--) {
t = typeof (j = prev[i]);
if (j != null && t === "object") {
j._pos = i;
} else if (t !== "object" && t != "undefined" ) break;
}
}
curr.sort (sorter);
if (prev) {
for (var k = prev.length,l,t;k>0;k--) {
t = typeof (l = prev[k]);
if (t === "object" && l != null) {
delete l._pos;
} else if (t !== "object" && t != "undefined" ) break;
}
}
return curr;
function sorter (a,b) {
var tStr = Object.prototype.toString
var types = [tStr.call(a),tStr.call(b)]
var ret = [0,0];
if (types[0] === types[1] && types[0] === "[object Object]") {
if (prev) return a._pos - b._pos
else {
return a === b ? 0 : 1;
}
} else if (types [0] !== types [1]){
return weight[types[0]] - weight[types[1]]
}
return a>b?1:a<b?-1:0;
}
}