我有一个Ruby程序,它接受一个HTML文档作为输入。这个HTML文档的结构是未知的,实际上可以是任何东西。
还保证文档使用CSS进行格式化。
输出需要是一个散列,其中每个键是文档中使用的一个CSS类,值是CSS类在文档主体中出现的次数
require 'open-uri'
require 'nokogiri'
doc = Nokogiri.HTML(open('http://stackoverflow.com'))
classes = doc.xpath('//@class').map{ |attr| attr.value.split(/s+/) }.flatten
counts = Hash[
classes.group_by(&:to_s).map{ |n,ary| [n,ary.count] }.sort_by{ |n,i| [-i,n] }
]
require 'pp'
pp counts
#=>{"post-tag"=>320,
#=> "mini-counts"=>270,
#=> "cp"=>90,
#=> "narrow"=>90,
#=> "question-hyperlink"=>90,
#=> ...etc...
描述:- 使用
xpath
查找所有class="..."
属性,例如class="a b"
,class="c"
,class="b"
-
split
对空白,例如class="a b"
⇒["a","b"]
-
flatten
合并为单个列表,例如[["a","b"],["c"],["b"]]
⇒["a","b","c","b"]
-
group_by
从字符串到命中的散列,例如:⇒{"a"=>["a"],"b"=>["b","b"],"c"=>["c"]}
-
map
与length
配对,例如:⇒[["a",1],["b",2],["c",1]]
- 为了好玩,
sort_by
的出现次数递减,例如:⇒[["b",2],["a",1],["c",1]]
-
Hash.[]
再次转换为散列,例如:⇒{"b"=>2,"a"=>1",c"=>1}
或者(不是函数式的,更直接)在第3步之后循环并将计数添加到散列中。为了获得额外的积分,使用默认的'0'值初始化哈希:
counts = Hash.new(0)
classes.each{ |name| counts[name] += 1 }