2010-06-10 2 views
2

Предположим, что у вас есть представление 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, чтобы выполнить эту работу, прежде чем передавать ее в шаблон?

ответ

1

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

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: вы также можете сделать это, вместо для цикла:

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

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

1

Как о чем-то вроде этого:

http://jsfiddle.net/9eXws/

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

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

0

Я думаю, что внутренний 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(); 
    }); 
}); 
0

Вместо того чтобы всегда перебирать каждый элемент и сравнивать каждый из них, вы должны использовать селекторы 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

Чувак ... Это просто многословный рефакторинг моего ответа, что я дал 13 часов назад, но с добавленным ', если()' оператором. – user113716

Смежные вопросы