0

次の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']
4

3 に答える 3

1

Nokogiri が何であるかはわかりませんが、HTML コードを String として持っている場合は、正規表現マッチングで注文を取得することができます。たとえば、次のようになります。

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 に注意する必要があります。それらは最初にエスケープする必要があります。

于 2009-05-06T16:31:53.680 に答える
0

これは同僚と私が思いついた解決策です:

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) }

最初に、HTML ドキュメントのすべての ID を配列に取得し、@un_array以前に作成した ID 配列に従って並べ替えます。

于 2009-05-07T13:39:53.023 に答える
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']

編集:これは同じ結果が得られるワンライナーですが、どちらが速いかを確認するためのベンチマークは行っていません。

ids = ['bar', 'para-3', 'para-2', 'para-7']
value.xpath("//*[@id]").collect {|node| node['id']} & ids
于 2009-05-06T16:37:29.377 に答える