Сравнение двух больших наборов атрибутов - PullRequest
2 голосов
/ 10 июня 2010

Предположим, у вас есть представление Django, которое имеет две функции:

Первая функция визуализирует некоторый XML с использованием таблицы стилей XSLT и создает div с 1000 подэлементами, например так:

<div id="myText">
    <p id="p1"><a class="note-p1" href="#" style="display:none" target="bot">✽</a></strong>Lorem ipsum</p>
    <p id="p2"><a class="note-p2" href="#" style="display:none" target="bot">✽</a></strong>Foo bar</p>
    <p id="p3"><a class="note-p3" href="#" style="display:none" target="bot">✽</a></strong>Chocolate peanut butter</p>
     (etc for 1000 lines)
    <p id="p1000"><a class="note-p1000" href="#" style="display:none" target="bot">✽</a></strong>Go Yankees!</p>
</div>

Вторая функция визуализирует другой XML-документ, используя другую таблицу стилей для получения div следующим образом:

<div id="myNotes">
    <p id="n1"><cite class="note-p1"><sup>1</sup><span>Trololo</span></cite></p>
    <p id="n2"><cite class="note-p1"><sup>2</sup><span>Trololo</span></cite></p>
    <p id="n3"><cite class="note-p2"><sup>3</sup><span>lololo</span></cite></p>
     (etc for n lines)
    <p id="n"><cite class="note-p885"><sup>n</sup><span>lololo</span></cite></p>
</div>

Мне нужно посмотреть, какие элементы в #myText имеют классы, которые соответствуют элементам в #myNotes, и отобразить их. Я могу сделать это с помощью следующего jQuery:

$('#myText').find('a').each(function() {
    var $anchor = $(this);
    $('#myNotes').find('cite').each(function() {
        if($(this).attr('class') == $anchor.attr('class')) {
            $anchor.show();
    });
});

Однако это невероятно медленно и неэффективно для большого числа сравнений.

Какой самый быстрый / самый эффективный способ сделать это - существует ли метод jQuery / js, который подходит для большого количества элементов? Или мне нужно переделать код Django, чтобы выполнить работу, прежде чем передавать его в шаблон?

Ответы [ 4 ]

1 голос
/ 10 июня 2010

Для достижения наилучшей производительности сделайте индекс один раз, а затем используйте его снова:

function revealCite() {
  var cites_index = $("#myText").data("cites_index");

  // if no cached index exists, prepare one (one-time hit code section)
  if (!cites_index) {
    var cites = $("#myNotes cite");
    var cites_count = cites.length();
    var cites_index = {};

    for (var i=0; i<cites_count; i++) {
      var cite = cites[i], group = cites_index[cite.className];
      if (!group) cites_index[cite.className] = [];
      group.push(cite);
    }
    $("#myText").data("cites_index", cites_index);
  }

  // use the index to work with related elements ("this" must be an <a> element)
  $(cites_index[this.className]).show();
}

Теперь запустите указанную выше функцию так, как вам нравится:

$("#myText a").each(revealCite);

PS:Вы также можете сделать это вместо цикла for:

cites.each( function() {
  var group = cites_index[this.className];
  if (!group) cites_index[this.className] = [];
  group.push(this);
});

Но это то же самое количество строк кода и, вероятно, немного медленнее.

1 голос
/ 10 июня 2010

Как насчет этого:

http://jsfiddle.net/9eXws/

$('#myText a').each(function() {
    $("#myNotes ." + $(this).attr('class')).show();
});​

Вместо внутреннего элемента он просто добавляет класс для текущего элемента a в селектор и выполняет show() для всех найденных элементов.

0 голосов
/ 11 июня 2010

Вместо того, чтобы постоянно проходить по каждому элементу и сравнивать каждый из них, вы должны использовать селекторы Jquery для поиска. Это должно работать значительно быстрее:

$('#myText > a').each(function() {
    var $anchor = $(this);
    var anchor_class = $(this).attr('class');
    var elements = $('#myNotes > cite[class=' + anchor_class + ']');
    if (elements[0] != undefined) {
        $anchor.show();
    }
});
0 голосов
/ 10 июня 2010

Я думаю, что внутреннее find избыточно повторяется для каждой итерации внешнего each.Попробуйте сохранить соответствующие элементы в переменной до начала цикла.Я также настроил ваше решение для получения имен классов через атрибут DOM, в отличие от использования jQuery attr:

var $cites = $('#myNotes').find('cite');
$('#myText').find('a').each(function() {
    var anchor = this;
    $cites.each(function() {
        if(this.className == anchor.className) {
            $anchor.show();
    });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...