2009-05-06 9 views
0

HTMLドキュメント内の順序に従ってIDのソート配列:鋸山:私はソートされていないアレイ保持次のID持って

@un_array = ['bar', 'para-3', 'para-2', 'para-7'] 

Nokogiriを使用して(またはプレーンのJavascript)のスマートな方法がありますが、応じて配列をソートします下のサンプルHTML文書のIDの順番に?

require 'rubygems' 
require 'nokogiri' 

value = Nokogiri::HTML.parse(<<-HTML_END) 
    "<html> 
    <head> 
    </head> 
    <body> 
     <p id='para-1'>A</p> 
     <div id='foo'> 
      <p id='para-2'>B</p> 
     <p id='para-3'>C</p> 
      <div id='bar'> 
       <p id='para-4'>D</p> 
       <p id='para-5'>E</p> 
       <p id='para-6'>F</p> 
     </div> 
     <p id='para-7'>G</p> 
     </div> 
     <p id='para-8'>H</p> 
    </body> 
    </html>" 
HTML_END 

この場合、その結果、ソートされた配列は次のようになります。

['para-2', 'para-3', 'bar', 'para-7'] 

答えて

0

これは同僚ソリューションであり、私が思いついた:私は、IDS-配列に応じて、私は私の並べ替え@un_arrayよりも、アレイにHTML文書のすべてのIDを取得

parent = value.css('body').first 
indexes = [] 
parent.children.each do |child| 
    indexes << child['id'] 
end 

puts @un_array.sort! { |x,y| indexes.index(x) <=> indexes.index(y) } 

ファースト前に作成されます。

1

ことが可能であるよりも、私は鋸山が何であるか知らないが、あなたはStringとしてHTMLコードを持っている場合例えば、正規表現のマッチングと順序を取得します

var str = '<html>...</html>'; // the HTML code to check 
var ids = ['bar', 'para-3', 'para-2', 'para-7']; // the array with all IDs to check 
var reg = new RegExp('(?:id=[\'"])('+ids.join('|')+')(?:[\'"])','g') // the regexp 
var result = [], tmp; // array holding the result and a temporary variable 
while((tmp = reg.exec(str))!==null)result.push(tmp[1]); // matching the IDs 
console.log(result); // ['para-2', 'para-3', 'bar', 'para-7'] 

あなたは正規表現のメタ文字を含むIDを持つように注意する必要があり、このコードを使用しました。彼らはまず脱出するべきです。

0

これは、Nokogiriでこれを行う方法の1つです。効率的なものが他にもあります。これが、DOM全体を歩くことになります。

require 'set' 

#Using a set here to make lookup O(1), because we don't care about the initial order 
id_set = ['bar', 'para-3', 'para-2', 'para-7'].to_set 
sorted = [] 

value.root.traverse do |node| 
    node_id = node['id'] 
    sorted << node_id if node_id && id_set.delete?(node_id) 
end 
# sorted is now ['para-2', 'para-3', 'bar', 'para-7'] 

EDIT:ここでは同じ結果を取得するワンライナーだが、私は高速であるかを確認するためにベンチマークを行っていません。

ids = ['bar', 'para-3', 'para-2', 'para-7'] 
value.xpath("//*[@id]").collect {|node| node['id']} & ids 
関連する問題