Posted in Javascript onJanuary 31, 2011
//灵感来自 //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; } }
javascript 节点排序 2
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@