Какой самый дешевый способ выбрать дочерний узел в Нокогири? - PullRequest
1 голос
/ 22 января 2010

Я знаю, что существуют десятки способов выбрать первый дочерний элемент в Нокогири, но какой самый дешевый? Я не могу обойтись, используя Node # children, что звучит ужасно дорого. Скажем, есть 10000 дочерних узлов, и я не хочу касаться 9999 других ...

Ответы [ 3 ]

2 голосов
/ 22 января 2010

Вы можете попробовать сами и оценить результат.

Я создал быстрый тест: http://gist.github.com/283825

$ ruby test.rb 
Rehearsal ---------------------------------------------------
xpath/first()     3.290000   0.030000   3.320000 (  3.321197)
xpath.first       3.360000   0.010000   3.370000 (  3.381171)
at                4.540000   0.020000   4.560000 (  4.564249)
at_xpath          3.420000   0.010000   3.430000 (  3.430933)
children.second   0.220000   0.010000   0.230000 (  0.233090)
----------------------------------------- total: 14.910000sec

                      user     system      total        real
xpath/first()     3.280000   0.000000   3.280000 (  3.288647)
xpath.first       3.350000   0.020000   3.370000 (  3.374778)
at                4.530000   0.040000   4.570000 (  4.580512)
at_xpath          3.410000   0.010000   3.420000 (  3.421551)
children.second   0.220000   0.010000   0.230000 (  0.226846)

Из моих тестов children представляется самым быстрым методом.

1 голос
/ 24 января 2010

Node # child - самый быстрый способ получить первый дочерний элемент.

Однако, если искомый узел НЕ является первым (например, 99-й), то более быстрого способа не существует.выбрать этот узел, чем вызывать #children и индексировать в него.

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

Oneограничивающим фактором является то, что libxml2 (библиотека XML, лежащая в основе Nokogiri) хранит дочерние узлы в виде связанного списка.Поэтому вам нужно будет пройти по списку (O (n)), чтобы выбрать нужный дочерний узел.

Можно было бы написать метод, который просто возвращает n-й дочерний элемент, без создания экземпляра NodeSet или даже ruby.предметы для всех остальных детей.Я бы посоветовал открыть запрос на добавление http://github.com/tenderlove/nokogiri/issues или отправить электронное письмо в список рассылки nokogiri.

0 голосов
/ 22 января 2010

Подход, который не использует XPath и не приводит к синтаксическому анализу всего родителя, заключается в использовании обоих узлов Node # child (), Node # next_sibling () и Node # element? ()

Как то так ...

def first(node)
    element = node.child
    while element
       if element.element?
           return element
       else
           element = element.next
       end
    end
    nil
end
...