在迭代期间从NodeSet中删除节点是否安全?我从一堆标签中拉出一些链接但是如果链接无效则想要从集合中删除标签。
def get_links(nodeset)
links = nodeset.map do |node|
begin
URI.join(node.document.url, node.get_attribute('href'))
rescue URI::InvalidURIError
nodeset.delete(node) # Is this safe?
nil
end
end
links.compact
end
答案 0 :(得分:1)
在您的示例代码中,我认为您并没有很好地分离您的行为。不要操纵nodeset
内的map
数组;并不是因为不能这样做,而是不应以保持清晰和易于维护。将地图“分开”与删除不良网址分开。
至少我会做更多的事情:
def get_valid_links(nodeset)
doc_url = nodeset.first.document.url
links = nodeset.map { |node|
begin
URI.join(doc_url, node['href'])
rescue URI::InvalidURIError
nil
end
end
links.compact
end
nodeset = get_valid_links(nodeset)
这样做不会改变nodeset
,除非您明确说明,通过分配从get_links
返回的压缩/映射值。这使得该方法的目的非常明确,并且没有副作用。
我认为这是“POLS”(“最小惊喜原则”)会起作用的案例之一。在方法中隐藏nodeset
的副作用可以对于那些试图维护代码或在库中使用它的人来说,这是非常令人惊讶的,并且很难解决。
根据经验,我建议您非常小心地将href
属性的内容放到URL的末尾,并期望它是好的或有用的。请记住,href
可能是一个JavaScript链接,这会产生一个丑陋的网址。