我知道有几十种方法可以选择Nokogiri的第一个子元素,但哪个最便宜? 我无法使用Node#children,这听起来非常昂贵。假设有10000个子节点,我不想触及9999个其他节点......
答案 0 :(得分:2)
您可以自己尝试并对结果进行基准测试。
我创建了一个快速基准: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 :(得分:1)
Node#child是获取第一个子元素的最快方法。
但是,如果您要查找的节点不是第一个节点(例如,第99个节点),则没有更快的方法来选择该节点,而不是调用#children并将其编入索引。
你说的是,如果你只想要第一个孩子,为所有孩子建立一个NodeSet是很昂贵的。
一个限制因素是libxml2(Nokogiri底层的XML库)将节点的子节点存储为链接列表。因此,您需要遍历列表(O(n))以选择所需的子节点。
编写一个简单地返回第n个子节点的方法是可行的,而不需要为所有其他子节点实例化NodeSet甚至ruby对象。我的建议是在http://github.com/tenderlove/nokogiri/issues打开功能请求,或发送电子邮件到nokogiri邮件列表。
答案 2 :(得分:0)
既不使用XPath也不导致解析整个父节点的方法是同时使用Node#child(),Node#next_sibling()和Node#元素?()
像这样......
def first(node)
element = node.child
while element
if element.element?
return element
else
element = element.next
end
end
nil
end