在迭代期间从节点集中删除节点是否安全?我正在从一堆标签中提取一些链接,但如果链接无效,我想从集合中完全删除标签。
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
在您的示例代码中,我认为您没有很好地分离您的操作。不要在map
内操纵您的nodeset
数组;不是你不能这样做,而是你不应该为了清晰和易于维护。"映射"URL与删除不良URL分开。
至少我会做一些更像的事情:
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链接,这将创建一个丑陋的URL。