检查Ruby Array是否以另一个Array启动

时间:2018-01-04 17:31:50

标签: arrays ruby

我正在尝试检查数组是否以另一个数组开始。

我设法编写了一些适合我用例的代码:

def self.array_start_with?(ary, beginning)
  return true if beginning.empty?

  ary[0..(beginning.size - 1)] == beginning
end

但它不是很漂亮的代码,我想知道是否有更惯用的方法。当开头为空但ary不是时,方法体内的第一个代码行是必需的。否则,开头将与ary整体进行比较(ary[0..-1])。我可以写:

ary[0..[beginning.size - 1, 0].max]

但那更加丑陋。

第二行代码不遵循元素的顺序,因为[1,2] == [2,1]在Ruby中为真。在我的具体实现中,这不是一个问题,因为输入中只能有一个元素的顺序,但我仍然很好奇是否存在更通用的解决方案。

编辑:[1,2] = = [2,1]的脑屁是真的。遗憾。

2 个答案:

答案 0 :(得分:2)

以下是一种方法:

ary.take(beginning.size) == beginning

一个优点是这适用于空阵列,因此您不需要额外检查。

答案 1 :(得分:0)

我需要非常快速地执行此计算,因此我创建了一个包含7种方法的基准测试:

require 'benchmark'

def candidate1(a, b)
  return false if b.size > a.size

  b.each_with_index do |el, i|
    return false if a[i] != el
  end

  true
end

def candidate2(a, b)
  return false if b.size > a.size

  i = 0
  b.each do |el|
    return false if a[i] != el
    i += 1
  end

  true
end

def candidate3(a, b)
  return false if b.size > a.size

  0.upto(b.size) do |i|
    return false if a[i] != b[i]
  end

  true
end

def candidate4(a, b)
  0.upto(b.size) do |i|
    return false if a[i] != b[i]
  end

  true
end

def candidate5(a, b)
  i = 0
  b.each do |el|
    return false if a[i] != el
    i += 1
  end

  true
end

def candidate6(a, b)
  return false if b.size > a.size

  i = -1
  b.each do |el|
    return false if a[i+=1] != el
  end

  true
end

def candidate7(a, b)
  a.take(b.size) == b
end

TEST_CASES = [
  [[3,3,3,3], [3,3,3,3]],
  [[3,3], [3,3,3,3]],
  [[3,3,3,3], [3,3]],
  [[1,2,3,4], [5,6,7,8]],
  [[1,2,3,4], [5,6,7]],
  [[], []],
  [[1,2,3,4],[1,2,3]],
  [[1,2,3,4,5,6,7,8,9,10,11,12,13],[1,2,3]],
  [[1,2,3],[1,2,3,4,5,6,7,8,9,10,11,12,13]]
]

N = 1_000_000

Benchmark.bm do |x|
  puts "Running all testcases #{N} times on each candidate"

  i = 1.upto(7) do |i|
    x.report do
      method_name = "candidate#{i}"
      puts method_name

      N.times do
        TEST_CASES.each_with_index do |c, j|
          send(method_name, c[0], c[1])
        end
      end
    end
  end
end

这就是我得到的:

candidate1
 4.713704   0.010974   4.724678 (  4.742682)
candidate2
 3.867821   0.009236   3.877057 (  3.888543)
candidate3
 5.521557   0.014552   5.536109 (  5.577994)
candidate4
 6.403158   0.010979   6.414137 (  6.428128)
candidate5
 4.730323   0.010388   4.740711 (  4.753335)
candidate6
 3.891551   0.021362   3.912913 (  3.964875)
candidate7
 3.942376   0.008003   3.950379 (  3.964634)

总结一下:候选人2和6总是胜过其他人,有时一个人获胜,有时另一个人:

def candidate2(a, b)
  return false if b.size > a.size

  i = 0
  b.each do |el|
    return false if a[i] != el
    i += 1
  end

  true
end

def candidate6(a, b)
  return false if b.size > a.size

  i = -1
  b.each do |el|
    return false if a[i+=1] != el
  end

  true
end