Как мне выполнить разницу двух строк или массивов в Ruby?
Diff строка или массив ruby
Ответ 1
diff.rb - это то, что вы хотите, которое доступно в http://users.cybercity.dk/~dsl8950/ruby/diff.html через интернет-архив:
http://web.archive.org/web/20140421214841/http://users.cybercity.dk:80/~dsl8950/ruby/diff.html
Ответ 2
Для массивов используйте оператор минус. Например:
>> foo = [1, 2, 3]
=> [1, 2, 3]
>> goo = [2, 3, 4]
=> [2, 3, 4]
>> foo - goo
=> [1]
Здесь последняя строка удаляет все из foo, которая также находится в goo, оставляя только элемент 1. Я не знаю, как это сделать для двух строк, но пока кто-нибудь, кто знает сообщения об этом, вы можете просто преобразовать каждый строка в массив, используйте минус-оператор, а затем преобразуйте результат назад.
Ответ 3
Я расстроился из-за отсутствия хорошей библиотеки для этого в рубине, поэтому я написал http://github.com/samg/diffy. Он использует diff
под обложками и фокусируется на удобстве и предоставляет довольно доступные параметры вывода.
Ответ 4
Для струн, я бы сначала попробовал Ruby Gem, что @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
Ответ 5
Существует также diff-lcs
, который доступен как драгоценный камень. Он не обновлялся с 2004 года, но мы использовали его без каких-либо проблем.
Изменить: В 2011 году была выпущена новая версия. Она выглядит в активной разработке.
Ответ 6
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
.
Ответ 7
Я только что нашел новый проект, который выглядит довольно гибким:
http://github.com/pvande/differ/tree/master
Попробуй это и попытаешься опубликовать какой-то отчет.
Ответ 8
У меня было такое же сомнение, и решение, которое я нашел, не на 100% рубине, но для меня лучше. Проблема с diff.rb заключается в том, что у нее нет красивого форматирования, чтобы показать различия в гуманизованном виде. Поэтому я использовал diff от ОС с помощью этого кода:
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
Ответ 9
Просто для людей Windows: diffy выглядит блестящим, но я верю, что он будет работать только на * nix (исправьте меня, если я ошибаюсь). Конечно, это не сработало на моей машине.
Дифференциал работал у меня (Windows 7 x64, Ruby 1.8.7).
Ответ 10
Возможно, Array.diff через monkey-patch помогает...
http://grosser.it/2011/07/07/ruby-array-diffother-difference-between-2-arrays/
Ответ 11
Чтобы получить символ по разрешению персонажа, я добавил новую функцию damerau-levenshtein gem
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