Ruby:如何找到2个数组之间的差异,订购问题

我正在尝试计算订单有效的两个数组之间的差异。 例如:

array_one = ["A", "B", "C"] array_two = ["B", "C", "A"] 

这将产生3个差异,因为:

 array_one[0] != array_two[0] array_one[1] != array_two[1] array_one[2] != array_two[2] 

另一个例子:

 array_one = ["Z", "X", "Y"] array_two = ["Z", "W", "Y"] 

这将产生1,因为:

 array_one[0] == array_two[0] array_one[1] != array_two[1] array_one[2] == array_two[2] 

任何建议都非常感谢。

这个怎么样

 array_one = ["A", "B", "C"] array_two = ["A", "C", "A"] array_one.select.each_with_index { |item, index| array_two[index] != item } => #B and C 

您可以使用zip合并两个数组,并计算两个值相等的内部数组。

 arr1 = [1,2,3] arr2 = [1,5,6] arr1.zip(arr2) #=> [[1, 1], [2, 5], [3, 6]] .count {|a, b| a == b} #=> 1 

另一种方法是只迭代两个数组并运行一个计数器

 count = 0 (0...arr1.length).each do |idx| count += 1 if arr1[idx] == arr2[idx] end 

当然,两者都假设两个数组的长度相同。

(0...arr1.length)0 to arr1.length-1...是独占的。

仅仅因为我喜欢这样的东西,我对解决方案进行了基准测试,只是想分享以防任何人感兴趣(我只是将数组切换到更大的数据以获得更有意义的结果)

 require "benchmark/ips" def method_1(ar_1, ar_2) ar = ar_1.zip ar_2 ar.count { |els| els[0] == els[1] } end def method_2(ar_1, ar_2) count = 0 ar_1.each_with_index { |el, i| count += 1 if el == ar_2[i] } end def method_3(ar_1, ar_2) count = 0 (0...ar_1.length).each do |idx| count += 1 if ar_1[idx] == ar_2[idx] end end def method_4(ar_1, ar_2) ar_1.zip(ar_2).inject(0) do |memo, (left, right)| if left == right memo else memo + 1 end end end def method_5(ar_1, ar_2) ar_1.select.each_with_index do |item, index| ar_2[index] != item end end Benchmark.ips do |x| # ar_1 = ["A", "B", "C"] # ar_2 = ["B", "C", "A"] ar_1 = (0..1_000_000).to_a.shuffle ar_2 = (0..1_000_000).to_a.shuffle x.report("zip and count") do |times| i = 0 while i < times method_1 ar_1, ar_2 i += 1 end end x.report("each with index") do |times| i = 0 while i < times method_2 ar_1, ar_2 i += 1 end end x.report("0..length each") do |times| i = 0 while i < times method_3 ar_1, ar_2 i += 1 end end x.report("zip and inject") do |times| i = 0 while i < times method_4 ar_1, ar_2 i += 1 end end x.report("select each with index") do |times| i = 0 while i < times method_5 ar_1, ar_2 i += 1 end end x.compare! end ################################################### # 10_000 elements per array # ################################################### # # Warming up -------------------------------------- # zip and count 54.000 i/100ms # each with index 92.000 i/100ms # 0..length each 87.000 i/100ms # zip and inject 41.000 i/100ms # select each with index # 82.000 i/100ms # Calculating ------------------------------------- # zip and count 545.700 (± 2.6%) i/s - 2.754k in 5.050362s # each with index 919.259 (± 3.0%) i/s - 4.600k in 5.008972s # 0..length each 919.908 (± 1.4%) i/s - 4.611k in 5.013518s # zip and inject 413.470 (± 1.7%) i/s - 2.091k in 5.058865s # select each with index # 828.774 (± 3.5%) i/s - 4.182k in 5.053036s # # Comparison: # 0..length each: 919.9 i/s # each with index: 919.3 i/s - same-ish: difference falls within error # select each with index: 828.8 i/s - 1.11x slower # zip and count: 545.7 i/s - 1.69x slower # zip and inject: 413.5 i/s - 2.22x slower ################################################### # 1_000_000 elements per array # ################################################### # # Warming up -------------------------------------- # zip and count 1.000 i/100ms # each with index 1.000 i/100ms # 0..length each 1.000 i/100ms # zip and inject 1.000 i/100ms # select each with index # 1.000 i/100ms # Calculating ------------------------------------- # zip and count 5.447 (±18.4%) i/s - 26.000 in 5.088342s # each with index 9.292 (± 0.0%) i/s - 47.000 in 5.058805s # 0..length each 9.104 (± 0.0%) i/s - 46.000 in 5.053701s # zip and inject 3.983 (± 0.0%) i/s - 20.000 in 5.042810s # select each with index # 7.777 (±12.9%) i/s - 39.000 in 5.053795s # # Comparison: # each with index: 9.3 i/s # 0..length each: 9.1 i/s - 1.02x slower # select each with index: 7.8 i/s - 1.19x slower # zip and count: 5.4 i/s - 1.71x slower # zip and inject: 4.0 i/s - 2.33x slower 

@ davidhu2000击败了我,但由于这种方法略有不同,可能仍值得一提:

 array_one = ["A", "B", "C"] array_two = ["B", "C", "A"] array_one.zip(array_two).inject(0) { |memo, (left, right)| unless left == right memo + 1 else memo end } # => 3 

这个怎么样

 array_one = ["A", "B", "C"] array_two = ["A", "C", "A"] array_one.select.each_with_index { |item, index| array_two[index] != item } => #["B", "C"] 
 array_one = ["A", "B", "C"] array_two = ["A", "C", "A"] enum_two = array_two.to_enum array_one.select { |s| s != enum_two.next } #=> ["B", "C"]