javascript - html片段去重,单层循环能搞定么?
伊谢尔伦
伊谢尔伦 2017-04-10 14:30:43
0
2
496

通常的去重是针对简单的数组,可以使用一个对象,将数组值作为对象属性,然后判断该对象的索引是否有定义。

var distinctArr = function(arr) {
    var i = 0,
        j = arr.length,
        cacheObj = {}, resArr = [];

    for (; i < j; i++) {
        if (!cacheObj[arr[i]]) {
            cacheObj[arr[i]] = 1;
            resArr.push(arr[i]);
        }
    }
    return resArr;
}

但是,怎么把DOM集合去重呢(把DOM集合 makeArray后)。
以上的方法针对DOM集合是无效的。

去重就是基于这种情形:

p>p>span

当我想用类似$('p span')的方式来获取span时(个人js原生实现,非jquery),我是先获取p,然后在得到的前一个结果集中寻找下一个符合条件的span,依此类推。

如此方法,我获取p,肯定得到的数组长度为2了。再寻找span时,就出问题了,按照这种方法寻找,肯定会找到两个相同的span了。

于是我就想得到所有结果后,进行一次过滤操作。

当然,还有一种方法好像在处理过程中用containscompareDocumentPosition来判断节点关系的,这样没必要进行去重操作了。

单层循环能搞定么,两层循环判断太慢了。

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

reply all(2)
迷茫

更新:以前的答案有问题,留着鞭尸吧……


Sizzle的去重流程可以参考:

  1. compareDocumentPosition或其shim来判断节点关系,sort你的DOM Array
  2. 然后判断Array中前后两个节点是否全等,全等则将相关的编号push入duplicate数组
  3. 逆向遍历duplicate数组,把DOM Array里面的重复节点全部都splice掉
Sizzle.uniqueSort = function( results ) {
    var elem,
        duplicates = [],
        j = 0,
        i = 0;

    results.sort( sortOrder );

    while ( (elem = results[i++]) ) {
        if ( elem === results[ i ] ) {
            j = duplicates.push( i );
        }
    }
    while ( j-- ) {
        results.splice( duplicates[ j ], 1 );
    }

    return results;
};

源码见这里

如果compareDocumentPosition被浏览器支持,那么去重循环是单层的,反之则需要用到二重循环的内层来shim compareDocumentPosition,判断节点关系,见这里

最好的情况下,Sizzle方案的消耗为:sort大致为O(nlogn) + 一重去重循环O(n) + DOM总开销(未知)。
有时间了跑一个benchmark。


不过compareDocumentPosition作为DOM Level 3的内容,它的浏览器兼容,据我点开这里测试,是这样的结果:

ie6 ie7 ie8 ie9 chrome  firefox
×   ×   ×   √   √   √

在支持它的浏览器(IE9+)里,也支持querySelectorAll(IE8+,见这里),我们自己做selector的意义不大;
反之,不支持它的浏览器,我们需要自己实现compareDocumentPosition,这样就多了一层循环,Sizzle方案里的双层循环去重恐怕不可避免。


当然,如果我们用一个唯一性ID标识所有的DOM节点,倒是可以单层循环去重。只不过这个方案的开销可不比Sizzle的方案小,还需要跟踪所有的DOM新增节点。


下面是尸体:

回到需求。

按照选择符描述去正向匹配是有这种过滤、父子层级的问题。这就是为什么CSS选择器的浏览器实现,以及高效的sizzle走了相反的路子:反向匹配。

这样的话,对于选择器p span,我们先找到所有的span,然后判断它的祖先层级是不是p。
你看,需要做去重吗?

想了一下,在这个问题上,读取的顺序不是太重要,对于这样的文档结构还是有重复的问题:

<p>
    <span></span>
    <p>
        <span></span>
    </p>
</p>
迷茫

用hash表

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template