is there any other simple,nicer
way?
require 'pp'
a1 = ["02/28/10","Webinars","131","0","26 Feb 2010","0","3d, 8h, 49m, 18s"]
a2 = ["02/20/10","Webinars","131","9","26 Feb 2010","0","3d, 8h, 49m, 18s"]
def compare(array1,array2,ignore)
tmp1 = Array.new
tmp2 = Array.new
0.upto(array1.length-1) {|index|
if !ignore.include?(index)
tmp1 << array1[index]
tmp2 << array2[index]
end
}
if tmp1 == tmp2
return true
else
return false
end
end
pp a1
pp a2
puts
puts compare(a1,a2,[0,3])
and the开发者_运维百科 output is
["02/28/10", "Webinars", "131", "0", "26 Feb 2010", "0", "3d, 8h, 49m, 18s"]
["02/20/10", "Webinars", "131", "9", "26 Feb 2010", "0", "3d, 8h, 49m, 18s"]
true
Simplest code (requires Ruby 1.8.7 or above):
def compare(array_a, array_b, ignore_list)
array_a.zip(array_b).each_with_index.all? do |a, b, idx|
a == b or ignore_list.include? idx
end
end
I suspect it will be faster, too (since it uses a single zip rather than individually asking the array for each item) — though this probably isn't a case where speed matters greatly.
As an aside, almost any time I'm directly indexing an array (like some_array[i]
) in Ruby rather than using a higher-order method such as map
or each
, I take that as a sign that I'm probably missing something in the standard library and the algorithm will probably be less efficient than the highly optimized library function.
There are probably plenty of more concise ways of doing this. Here's the first that came to my mind, which I'm sure could be improved upon.
def compare(array1, array2, ignore)
return false if array1.size != array2.size
0.upto(array1.size) do |i|
return false if !ignore.include?(i) && array1[i] != array2[i]
end
return true
end
Essentially, a manual array comparison. Check for same size, then check the elements one by one (but ignoring indices we are told to ignore). Break as soon as we know it's pointless to proceed.
This looks better to me :) :
def compare(array1, array2 = [], ignore = [])
return false if array1.length != array2.length
array1.each_with_index.all? do |e1, i1|
array2[i1] == e1 || ignore.include?(i1)
end
end
The beauty of this is that it "chains" each_with_index
with all?
making much cleaner code.
The bad is that it only works from Ruby 1.8.7. Anyway do not see a reason to use < 1.8.7
How about this?
require 'enumerator'
def compare (a1, a2, i)
a1.size == a2.size and
( a1.enum_for(:each_with_index).select{ |v, j| !i.include?(j)} ==
a2.enum_for(:each_with_index).select{ |v, j| !i.include?(j)} )
end
compare([1,2,3,4,5], [1,7,6,4,5], [1,2]) #true
compare([1,2,3,4,5], [1,7,6,4,5], [1,2]) #true
Note
This will work in Ruby 1.8.6. You can use Dmitriy Nagirnyak
's method to optimize this further:
def compare (a1, a2, i)
a1.size == a2.size and
a1.enum_for(:each_with_index).all?{|v, j| a2[j] == v or i.include?(j)}
end
Here's a solution for 1.9 that compares the arrays for < and > as well as ==:
#!/usr/bin/ruby1.9
# Return -1 if array1 < array2
# 0 if array1 == array2
# +1 if array1 > array2
# ignore contains indices of elements to ignore
def compare(array1, array2, ignore)
filter = lambda do |a|
a.collect.with_index do |e, i|
if ignore.include?(i)
''
else
e
end
end
end
filter[array1] <=> filter[array2]
end
array1 = ["02/28/10","Webinars","131","0","26 Feb 2010","0","3d, 8h, 49m, 18s"]
array2 = ["02/20/10","Webinars","131","9","26 Feb 2010","0","3d, 8h, 49m, 18s"]
p compare(array1, array2, [0, 3]) # => 0
p compare(array1, array2, [0]) # => -1
p compare(array1, array2, [3]) # => 1
Here's another one, terse and highly inefficient:
def compare a1, a2, i
[a1,a2].map { |a|
a.values_at(*((0...a.length).to_a - i))
}.inject(&:==)
end
精彩评论