javascript 节点排序 2

 更新时间:2011年01月31日 19:02:09   作者:  
对支持sourceIndex的HTML文档的节点重排,使用JK提供的思路,速度至少比单纯使用nodes.sort(function(a,b){return a.sourceIndex - b.sourceIndex})这种方式快两倍
复制代码 代码如下:

//灵感来自
//http://www.cnblogs.com/jkisjk/archive/2011/01/28/array_quickly_sortby.html
var hasDuplicate = false;
var sortBy = function(nodes){
var result = [], array = [], n = nodes.length, i = n, node;
while(node = nodes[--n]){
(array[n] = new Number(~~node.sourceIndex))._ = node;
}
array.sort(function(a,b){
if(a === b) hasDuplicate = true;
return a - b ;
});
while( i )
result[--i] = array[i]._;
return result;
}

但标准浏览器不支持这属性,在IE中,XML文档也没有此属性,这时就需要跟据节点的parentNode与nextSibling,但如果单单是两两比较,速度是提升不了的。因此我们就转而比较最近公共祖先的孩子们的顺序了。这时,算法的威力就体现出来了。这是第一版,根据某一朋友提供的LCA搞出来的东西,当然大体思路还是归功于JK大神。但实际效果不如意,比jQuery的那个sortOrder慢,估计问题出在求LCA上。
复制代码 代码如下:

//根据这里JK提供的思路
//http://www.cnblogs.com/rubylouvre/archive/2011/01/28/1947286.html#2020900
var tick = 0, hasDuplicate = false;
var Rage = {
//form http://www.cnblogs.com/GrayZhang/archive/2010/12/29/find-closest-common-parent.html
getLCA:function(nodes){
var hash = {}, i = 0,
attr = "data-find"+(++tick),
length = nodes.length,
node,
parent,
counter = 0,
uuid;
while(node = nodes[i++]){
parent = node;
while(parent){
if(parent.nodeType === 1){
break;
}
uuid = parent.getAttribute(attr);
if(!uuid){
uuid = "_" + (++counter);
parent.setAttribute(attr,uuid);
hash[uuid] = {node:parent,count:1};
}else{
hash[uuid].count ++;
}
parent = parent.parentNode;
}
}
for(var i in hash){
if(hash[i].count === length){
return hash[i].node;
}
}
},
getList : function(nodes,parent){//获取当前元素到最近公共祖先间的所有祖先,包括自己
var list = [];
while(node){
if(node === parent){
break;
}
list.unshift(node);
node = node.parentNode;
}
return list;
},
getLists : function(){
var lists = [], getList = Rage.getList, i=0, node, list;
while(node = nodes[i++]){
list = getList(node,parent);
if(list.length){
lists[ lists.length ] = list;
}
}
return lists;
},
sortList : function(a,b){
var n = Math.min(a.length,b.length),ap,bp;
for(var i=0; i < n; i++){
ap = a[i],bp = b[i]
if(ap !== bp){
while(ap = ap.nextSibling){
if(ap === bp){
return -1
}
}
return 1
}
}
return a.length-b.length;
},
uniqueSort : function(nodes){
var length = nodes.length;
var LCA = Rage.getLCA(nodes);
var lists = Rage.getLists(nodes,LCA);
lists.sort(Rage.sortList);
var list, i = 0, result = [];
while(list = lists[i++]){
result[result.length] list.pop();
}
if(result.length !== length){
result.unshift(LAC);
if(result.length != length){
hasDuplicate = true;
}
}
return result;
}
}

下面是第二版,经过改进,终于比jQuery的那个快上三倍(测试对象为拥有260多个节点的文档)
复制代码 代码如下:

var hasDuplicate = false;
var Rage = {
getList : function(node){
var list = [];
while(node){
if(node.nodeType === 9){
break;
}
list.unshift(node);
node = node.parentNode;
}
return list;
},
getLists : function(nodes){
var lists = [], getList = Rage.getList, i=0, node;
while(node = nodes[i++]){
lists[ lists.length ] = getList(node);
}
return lists;
},
sliceList : function(lists,num){
var result = [], i = 0, list;
while(list = lists[i++]){
list = list.slice(num);
if(list.length){
result[ result.length ] = list;
}
}
return result;
},
sortList : function(a,b){
var n = Math.min(a.length,b.length),ap,bp;
for(var i=0; i < n; i++){
ap = a[i],bp = b[i]
if(ap !== bp){
while(ap = ap.nextSibling){
if(ap === bp){
return -1
}
}
return 1
}
}
return a.length-b.length;
},
uniqueSort : function(nodes){
var length = nodes.length;
var lists = Rage.getLists(nodes);
lists.sort(function(a,b){
return a.length - b.length;
});
var depth = lists[0].length, length = lists.length, parent, cut, ii = 0;
for(var i =0; i < depth; i++){
parent = lists[0][i];
cut = true;
for(var j = 1;j < length; j++){
if(parent !== lists[j][i]){
cut = false;
break;
}
}
if(cut){
ii++
}else{
break;
}
}
var LCA = lists[0][ii-1];
lists = Rage.sliceList(lists,ii);
lists.sort(Rage.sortList);
var list, i = 0, result = [];
while(list = lists[i++]){
result[result.length] = list.pop();
}
if(result.length !== length){
result.unshift(LCA);
if(result.length != length){
hasDuplicate = true;
}
}
return result;
}
}

相关文章

  • TableSort.js表格排序插件使用方法详解

    TableSort.js表格排序插件使用方法详解

    这篇文章主要为大家详细介绍了TableSort.js表格排序插件的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • js实现跨域访问的三种方法

    js实现跨域访问的三种方法

    这篇文章主要介绍了js实现跨域访问的三种方法,包括基于iframe实现跨域、基于script标签实现跨域以及后台代理方式 ,感兴趣的小伙伴们可以参考一下
    2015-12-12
  • JavaScript WebSocket实现实时双向聊天

    JavaScript WebSocket实现实时双向聊天

    这篇文章主要为大家详细介绍了如何基于JavaScript WebSocket实现实时双向聊天,文中的示例代码讲解详细,有需要的小伙伴可以参考一下
    2024-04-04
  • JS中FRAME的操作问题实例分析

    JS中FRAME的操作问题实例分析

    这篇文章主要介绍了JS中FRAME的操作问题实例分析,详细讲述了js针对frame框架操作中的各种访问问题,需要的朋友可以参考下
    2014-10-10
  • 老生常谈JavaScript中的this关键字

    老生常谈JavaScript中的this关键字

    相对于很多其他的面向对象语言来说,this代表的就是当前对象。本篇文章通过实例给大家介绍js中的this关键字,感兴趣的朋友一起看看吧
    2016-10-10
  • js给页面加style无效果的解决方法

    js给页面加style无效果的解决方法

    js给页面加style没有效果的情况,想必大家都有见到吧,下面有个不错的解决方法,大家可以参考下
    2014-01-01
  • 在多个页面使用同一个HTML片段《续》

    在多个页面使用同一个HTML片段《续》

    上一篇文章中我们使用textarea来模拟AJAX的返回结果,造成了一些误解。 这里我们首先用asp.net的Generic Handler做一个简单的后台来重现这个AJAX过程。
    2011-03-03
  • 利用vscode调试编译后的js代码详解

    利用vscode调试编译后的js代码详解

    看了网上好多在vscode上调试javascript的代码,总是出现问题,索性自己写一个,下面这篇文章主要给大家介绍了关于如何利用vscode调试编译后的js代码的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们一起来看看吧
    2018-05-05
  • 原生js实现鼠标跟随效果

    原生js实现鼠标跟随效果

    本文主要分享了原生js实现鼠标跟随效果的实例,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • JavaScript之filter_动力节点Java学院整理

    JavaScript之filter_动力节点Java学院整理

    filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。下面通过实例代码给大家简答介绍下javascript中的filter,需要的的朋友参考下吧
    2017-06-06

最新评论