سؤال

كيف أقوم بعمل فرق بين سلسلتين أو صفائف في روبي؟

هل كانت مفيدة؟

المحلول

نصائح أخرى

بالنسبة للمصفوفات، استخدم عامل التشغيل ناقص.على سبيل المثال:

>> foo = [1, 2, 3]
=> [1, 2, 3]
>> goo = [2, 3, 4]
=> [2, 3, 4]
>> foo - goo
=> [1]

هنا يزيل السطر الأخير كل شيء من foo الموجود أيضًا في goo، ويترك العنصر 1 فقط.لا أعرف كيفية القيام بذلك لسلسلتين، ولكن حتى يتمكن شخص يعرف المنشورات حول هذا الموضوع، يمكنك فقط تحويل كل سلسلة إلى مصفوفة، واستخدام عامل التشغيل ناقص، ثم تحويل النتيجة مرة أخرى.

لقد شعرت بالإحباط بسبب عدم وجود مكتبة جيدة لهذا في روبي، لذلك كتبت http://github.com/samg/diffy.يستخدم diff تحت الأغطية، ويركز على أن يكون ملائمًا، ويوفر خيارات إخراج جميلة.

بالنسبة للسلاسل، سأحاول أولاً تجربة جوهرة الياقوت التي ذكرها @sam-saffron أدناه.إنه أسهل في التثبيت:http://github.com/pvande/differ/tree/master

gem install differ

irb
require 'differ'

one = "one two three"
two = "one two 3"

Differ.format = :color
puts Differ.diff_by_word(one, two).to_s

Differ.format = :html
puts Differ.diff_by_word(one, two).to_s

لقد نجح HTMLDiff الذي ذكره @da01 أعلاه بالنسبة لي.

script/plugin install git://github.com/myobie/htmldiff.git

# bottom of environment.rb
require 'htmldiff'

# in model
class Page < ActiveRecord::Base
  extend HTMLDiff
end

# in view
<h1>Revisions for <%= @page.name %></h1>
<ul>
<% @page.revisions.each do |revision| %>
  <li>
    <b>Revised <%= distance_of_time_in_words_to_now revision.created_at %> ago</b><BR>
      <%= Page.diff(
        revision.changes['description'][0],
        revision.changes['description'][1]
      ) %>
      <BR><BR>
  </li>
<% end %>

# in style.css
ins.diffmod, ins.diffins { background: #d4fdd5; text-decoration: none; }
del.diffmod, del.diffdel { color: #ff9999; }

تبدو جيدة.بالمناسبة لقد استخدمت هذا مع acts_as_audited توصيل في.

يوجد ايضا diff-lcs والذي يتوفر كجوهرة. لم يتم تحديثه منذ عام 2004 ولكن لقد تم استخدامه دون أي مشكلة.

يحرر: تم إصدار نسخة جديدة في عام 2011.يبدو أنه عاد إلى التطوير النشط.

http://rubygems.org/gems/diff-lcs

t=s2.chars; s1.chars.map{|c| c == t.shift ? c : '^'}.join

هذا الخط البسيط يعطي ^ في المواقف التي لا تتطابق.وهذا غالبًا ما يكفي وهو قابل للنسخ/اللصق.

لقد وجدت للتو مشروعًا جديدًا يبدو مرنًا جدًا:

http://github.com/pvande/differ/tree/master

جربه وسيحاول نشر نوع من التقرير.

كان لدي نفس الشك والحل الذي وجدته ليس روبيًا بنسبة 100٪، ولكنه الأفضل بالنسبة لي.المشكلة في diff.rb هي أنه لا يحتوي على منسق جميل لإظهار الاختلافات بطريقة إنسانية.لذلك استخدمت فرقًا من نظام التشغيل بهذا الرمز:

 def diff str1, str2
   system "diff #{file_for str1} #{file_for str2}"
 end

 private
 def file_for text
   exp = Tempfile.new("bk", "/tmp").open
   exp.write(text)
   exp.close
   exp.path
 end

فقط لصالح مستخدمي Windows:يبدو diffy رائعًا ولكني أعتقد أنه لن يعمل إلا على * nix (صححني إذا كنت مخطئًا).بالتأكيد لم يعمل على جهازي.

كان الاختلاف بمثابة متعة بالنسبة لي (Windows 7 x64، Ruby 1.8.7).

ربما يساعد Array.diff عبر Monkey-patch ...

http://grosser.it/2011/07/07/ruby-array-diffother-difference-between-2-arrays/

للحصول على دقة الأحرف حسب الأحرف أضفت وظيفة جديدة إليها جوهرة داميراو-ليفنشتاين

require "damerau-levenshtein"
differ = DamerauLevenshtein::Differ.new
differ.run "Something", "Smothing"
# returns ["S<ins>o</ins>m<subst>e</subst>thing", 
#  "S<del>o</del>m<subst>o</subst>thing"]

أو مع التحليل:

require "damerau-levenshtein"
require "nokogiri"

differ = DamerauLevenshtein::Differ.new
res = differ.run("Something", "Smothing!")
nodes = Nokogiri::XML("<root>#{res.first}</root>")

markup = nodes.root.children.map do |n|
  case n.name
  when "text"
    n.text
  when "del"
    "~~#{n.children.first.text}~~"
  when "ins"
    "*#{n.children.first.text}*"
  when "subst"
    "**#{n.children.first.text}**"
  end
end.join("")

puts markup
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top