从顶层到底层对 DOM 节点数组进行排序

发布于 2025-01-03 21:52:06 字数 621 浏览 0 评论 0原文

我有一个 DOM 节点数组(一个 javascript 数组,而不是 jQuery 对象),它充当处理它们的函数的队列。该数组可能包含具有父/子、祖父母/子等关系的元素。我总是希望首先处理更高级别的元素。我的第一个想法是在 javascript 中创建一个快速排序函数,但我知道如果我可以使用 javascript 的原生 Array.prototype.sort 方法,速度会更快。

我尝试了这样的方法:

domElements.sort(function (a, b) {
  return $(a).find(b).length ? 1 :
         $(b).find(a).length ? -1 :
         0;
});

但它似乎并没有完美地排序。有时我仍然会在父母之前拥有子元素。为什么这不起作用?有没有办法用 javascript 的原生排序来做到这一点?

更新:在调查了答案中的方法后,我想知道它们的表现如何。 这里是结果。请随意调整,看看性能如何适合您。

I have an array (a javascript array, not a jQuery object) of DOM nodes that acts as a queue for a function I have that processes them. This array could potentially contain elements that have parent/child, grandparent/child, etc. relationships. I always want higher-level elements to be processed first. My first inclination was to whip up a quicksort function in javascript, but I knew it would be faster if I could use javascript's native Array.prototype.sort method.

I tried it this way:

domElements.sort(function (a, b) {
  return $(a).find(b).length ? 1 :
         $(b).find(a).length ? -1 :
         0;
});

But it didn't seem to sort it perfectly. I would still sometimes have child elements before their parents. Why doesn't this work? Is there a way to do this with javascript's native sort?

UPDATE: After surveying the methods in the answers, I wanted to know how they performed. Here are the results. Feel free to tweak and see how the performance is for you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

淡淡绿茶香 2025-01-10 21:52:06

您可以使用 jQuery 的 unique 方法节省一些时间:http://api. jquery.com/jQuery.unique/

jQuery.unique(domElements);

You can save some time by using jQuery's unique method: http://api.jquery.com/jQuery.unique/

jQuery.unique(domElements);
江南烟雨〆相思醉 2025-01-10 21:52:06

(既然你要求我发布它。:-) )

你说过你想要父元素数组中的子元素之前,但是你的代码

domElements.sort(function (a, b) {
  return $(a).find(b).length ? 1 :
         $(b).find(a).length ? -1 :
         0;
});

...返回1 如果 ab 的父级,这会将 a 稍后放入数组比b

所以我在想:

domElements.sort(function (a, b) {
  return $(a).find(b).length ? -1 :
         $(b).find(a).length ? 1 :
         0;
});

但是检查一个元素是否是另一个元素的后代是如此简单,我想知道你是否真的需要 allocate-a-jQuery-object-and-then-call-find:

domElements.sort(function (a, b) {
  return isParentOf(a, b) ? -1 :
         isParentOf(b, a) ? 1 :
         0;
});

function isParentOf(parent, elm) {
    while (elm) {
        elm = elm.parentNode;
        if (elm === parent) {
            return true;
        }
    }
    return false;
}

工作示例 但请注意timmywil 的答案 ——尽管它做了一些不必要的工作(将兄弟姐妹排序,当你只关心父母时) /child),有一个预制的 jQuery 函数!

(Since you asked me to post it. :-) )

You've said you want the parent elements before the children in the array, but your code

domElements.sort(function (a, b) {
  return $(a).find(b).length ? 1 :
         $(b).find(a).length ? -1 :
         0;
});

...returns 1 if a is a parent of b, which will put a later in the array than b.

So I'm thinking:

domElements.sort(function (a, b) {
  return $(a).find(b).length ? -1 :
         $(b).find(a).length ? 1 :
         0;
});

But checking if an element is a descendant of another element is so straight-forward, I wonder if you really need the allocate-a-jQuery-object-and-then-call-find:

domElements.sort(function (a, b) {
  return isParentOf(a, b) ? -1 :
         isParentOf(b, a) ? 1 :
         0;
});

function isParentOf(parent, elm) {
    while (elm) {
        elm = elm.parentNode;
        if (elm === parent) {
            return true;
        }
    }
    return false;
}

Working example But note timmywil's answer — even though it does a bit of unnecessary work (putting the siblings in order, when all you care about is parent/child), there's a pre-baked jQuery function for that!

不…忘初心 2025-01-10 21:52:06

看来我混合了一个否定号:

domElements.sort(function (a, b) {
  return $(a).find(b).length ? -1 :
         $(b).find(a).length ? 1 :
         0;
});

似乎有效。

It looks like I mixed around the negative sign on the one:

domElements.sort(function (a, b) {
  return $(a).find(b).length ? -1 :
         $(b).find(a).length ? 1 :
         0;
});

Seems to work.

森林很绿却致人迷途 2025-01-10 21:52:06

根据源代码顺序对文档中的随机元素进行排序将
将子节点和兄弟节点保持在适当的位置。

if(!Array.prototype.indexOf){
    Array.prototype.indexOf= function(what, i){
        if(typeof i!= 'number') i= 0;
        var L= this.length;
        while(i< L){
            if(this[i]=== what) return i;
            ++i;
        }
        return -1;
    }
}
function nodeSort(nodesArray, pa){
    pa= pa || document;
    var original= [], src= pa.getElementsByTagName('*'), L= src.length;
    for(var i= 0; i<L; i++){
        if(nodesArray.indexOf(src[i])!=-1) original.push(src[i]);
    }
    return nodesArray.sort(function(a, b){
        return original.indexOf(a)- original.indexOf(b);
    });
}

Sorting random elements in a document according to their source code order will
keep childnodes and siblings in their proper positions.

if(!Array.prototype.indexOf){
    Array.prototype.indexOf= function(what, i){
        if(typeof i!= 'number') i= 0;
        var L= this.length;
        while(i< L){
            if(this[i]=== what) return i;
            ++i;
        }
        return -1;
    }
}
function nodeSort(nodesArray, pa){
    pa= pa || document;
    var original= [], src= pa.getElementsByTagName('*'), L= src.length;
    for(var i= 0; i<L; i++){
        if(nodesArray.indexOf(src[i])!=-1) original.push(src[i]);
    }
    return nodesArray.sort(function(a, b){
        return original.indexOf(a)- original.indexOf(b);
    });
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文