سؤال

لدي لم يتم فرزها مجموعة عقد المعرفات التالية:

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

هل هناك طريقة ذكية باستخدام Nokogiri (أو عادي جافا سكريبت) لفرز مجموعة وفقا لأمر معرفات في المثال مستند HTML أدناه ؟

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']
هل كانت مفيدة؟

المحلول 3

وهذا هو الحل زميل العمل وخطرت لي:

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 إلى صفيف، مما كنت فرز @un_array وفقا لمعرفات صفيف أنا خلقت من قبل.

نصائح أخرى

وأنا لا أعرف ما هو Nokogiri، ولكن إذا كان لديك رمز 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']

وباستخدام هذا الرمز عليك أن تكون حذرا مع معرفات تحتوي على التعبير العادي الفوقية حرفا. وينبغي أن هرب أولا.

هنا طريقة واحدة للقيام بذلك في Nokogiri - قد يكون هناك غيرها والتي هي أكثر كفاءة ، كما أن هذا ينتهي المشي كامل دوم.

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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top