• 选择器对节点去重的处理


    由于存在并联选择器,因此就算是从右到左过滤结果集,还是存在去重问题。排序问题产说了,以前JK已经给出非常逆天的算法。现在看一下去重问题。其实你们可以看成是一个纯粹的数组去重问题。难度在于速度。因此mootools搞出slickspeed这东西,引发了速度竞赛。现在让我们看看几个去重函数的实现了。

       var unique = function(array) {
            var ret = [];
            o:for(var i = 0, n = array.length; i < n; i++) {
                for(var x = i + 1 ; x < n; x++) {
                    if(array[x] === array[i])
                        continue o; 
                }
                ret.push(array[i]);
            }
            return ret;
        }
     

    这是早期mass Framework的方案,不打乱顺序的

    function uniq(array){
        var ret = [],ri = 0
        array = array.sort();
        ret[ri] = array[0];
         
        for(var j = 1, n = array.length; j < n; j++){
            if(ret[ri] !== array[j]){
                ret[++ri] = array[j]
            }
        }
        return ret;
    }
    

    这是打乱顺序的。

    
     /* 快速除重,相对于ArrayH.unique,为了效率,牺了代码量与严谨性。如果数组里有不可添加属性的对象,则会抛错.
    		 * @method quicklyUnique
    		 * @static
    		 * @param {array} arr 待处理数组
    		 * @return {array} 返回除重后的新数组
    		 */
    		quicklyUnique: function(arr) {
    			var strs = {},
    				numAndBls = {},
    				objs = [],
    				hasNull,
    				hasUndefined,
    				ret = [];
    			for (var i = 0, len = arr.length; i < len; i++) {
    				var oI = arr[i];
    				if (oI === null) {
    					if (!hasNull) {
    						hasNull = true;
    						ret.push(oI);
    					}
    					continue;
    				}
    				if (oI === undefined) {
    					if (!hasUndefined) {
    						hasUndefined = true;
    						ret.push(oI);
    					}
    					continue;
    				}
    				var type = typeof oI;
    				switch (type) {
    				case 'object':
    				case 'function':
    					if (!oI.__4QuicklyUnique) {
    						oI.__4QuicklyUnique = true;
    						ret.push(oI);
    						objs.push(oI);
    					}
    					break;
    				case 'string':
    					if (!strs[oI]) {
    						ret.push(oI);
    						strs[oI] = true;
    					}
    				default:
    					if (!numAndBls[oI]) {
    						ret.push(oI);
    						numAndBls[oI] = true;
    					}
    					break;
    				}
    			}
    			for (i = 0; oI = objs[i++];) {
    				if (oI instanceof Object) {
    					delete oI.__4QuicklyUnique;
    				} else {
    					oI.__4QuicklyUnique = undefined;
    				}
    			}
    			return ret;
    		},
    

    这是qwrap框架提供的方案,利用经典的hash去重法,但这要对对象类型的元素做些手段,因此它只是候选放案。像网上那些流行的普通hash去重法更是经不起推敲。

    	unique: function(arr) {
    			var rlt = [],
    				oI = null,
    				indexOf = Array.indexOf || ArrayH.indexOf;
    			for (var i = 0, len = arr.length; i < len; i++) {
    				if (indexOf(rlt, oI = arr[i]) < 0) {
    					rlt.push(oI);
    				}
    			}
    			return rlt;
    		},
    

    这是qwrap现时的方案,运用原生Array.prototype.indexOf,不支持需要自己做个轮子。

            unique: function ( target ) {
                var ret = [], n = target.length, i, j;
                for (i = 0; i < n; i++) {
                    for (j = i + 1; j < n; j++)
                        if (target[i] === target[j])
                            j = ++i;
                    ret.push(target[i]);
                }
                return ret;
            },
    

    这是mass Framework正在采用的方案,由群里的abcd提供。

    Sizzle.uniqueSort = function( results ) {
    	if ( sortOrder ) {
    		hasDuplicate = baseHasDuplicate;
    		results.sort( sortOrder );
    
    		if ( hasDuplicate ) {
    			for ( var i = 1; i < results.length; i++ ) {
    				if ( results[i] === results[ i - 1 ] ) {
    					results.splice( i--, 1 );
    				}
    			}
    		}
    	}
    
    	return results;
    };
    

    这是 jQuery 1.7 前的方案,直接在原数组上操作,如果数组很大,会容易搞死IE6。由于处理的是节点,要保持像querySelectorAll那样的效果,需要按DOM树出现顺序重排。

    
    Sizzle.uniqueSort = function( results ) {
    	var elem,
    		i = 1;
    
    	hasDuplicate = baseHasDuplicate;
    	results.sort( sortOrder );
    
    	if ( hasDuplicate ) {
    		for ( ; (elem = results[i]); i++ ) {
    			if ( elem === results[ i - 1 ] ) {
    				results.splice( i--, 1 );
    			}
    		}
    	}
    
    	return results;
    };
    

    jquery1.8的实现,它不再访问数组的 length 属性,提高了运行效率。每次以 elem = results[i] 赋值后是否存在为循环判定条件。

    Sizzle.uniqueSort = function( results ) {
    	var elem,
    		duplicates = [],
    		i = 1,
    		j = 0;
    
    	hasDuplicate = baseHasDuplicate;
    	results.sort( sortOrder );
    
    	if ( hasDuplicate ) {
    		for ( ; (elem = results[i]); i++ ) {
    			if ( elem === results[ i - 1 ] ) {
    				j = duplicates.push( i );
    			}
    		}
    		while ( j-- ) {
    			results.splice( duplicates[ j ], 1 );
    		}
    	}
    
    	return results;
    };
    

    jquery1.83的实现,它是先保持了索引值,然后从后面开始删除,避免数组索引的改动导致删除错误。

    但明显jquery.unique不能用于普通的数组去重。因此在mass Framework它们是不相干的两个函数。

    机器瞎学/数据掩埋/模式混淆/人工智障/深度遗忘/神经掉线/计算机幻觉/专注单身二十五年
  • 相关阅读:
    Windows删除git本地记住的密码
    C++ fmt库的安装和测试
    仿照struct is_integral 实现struct not_int
    folly库net库udp小例子
    Java阻塞队列BlockingQueue
    正则表达式必知必会摘要
    正则表达式匹配IP地址
    SimpleDateFormat线程安全性测试与解决方案
    Java8 HashMap中哈希桶(table)数组的索引位置
    socket网络编程--基础应用篇
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/2817654.html
Copyright © 2020-2023  润新知