即使在更改为整数之后,Fixnum与nil的比较也会失败

时间:2014-05-29 00:21:06

标签: ruby arrays sorting

我正在学习Ruby并插入排序算法。

以下代码在comparison of Fixnum with nil failed时出错,我不确定原因。

我感谢任何投入。

def insert_sort(arr)
  arr = arr.map(&:to_i) # change string in array to integer
  [*1..arr.length].each do |j|
    key = arr[j]
    i = j - 1
    while i >= 0 and arr[i] > key # error in this line
      arr[i + 1] = arr[i]
      i = i - 1
    end
    arr[i + 1] = key
  end
end

错误详情:

Failure/Error: insert_sort([5, 2, 4, 6, 1, 3]).should == [1,2,3,4,5,6]
 ArgumentError:
   comparison of Fixnum with nil failed
 # ./lib/insert_sort.rb:6:in `>'
 # ./lib/insert_sort.rb:6:in `block in insert_sort'
 # ./lib/insert_sort.rb:3:in `each'
 # ./lib/insert_sort.rb:3:in `insert_sort'
 # ./spec/lib/insert_sort_spec.rb:6:in `block (2 levels) in <top (required)>'

原始伪代码:

1 for j = 2 to A.length
2 key = A[j]
3 // Insert A[j] into the sorted sequence A[1..j-1].
4 i=j-1
5 while i>0 and A[i] > key
6 A[i+1] = A[i]
7 i = i - 1
8 A[i+1]=key

2 个答案:

答案 0 :(得分:2)

为了让你的方法正常工作,它应该是:

[*1..arr.length].each do |j|
  key = arr[j - 1]

答案 1 :(得分:1)

这是一种类似Ruby的方式来编写它。通过尽可能少地使用索引,可以减少出错的可能性,就像你拥有的那样。

def insert_sort(arr)
  arr.each_with_object([]) do |e,a|
    ei = e.to_i
    i = a.index { |f| ei < f } || a.size
    a.insert(i,ei)
  end
end

insert_sort(['7','3','1','5','2','8']) #=> [1, 2, 3, 5, 7, 8]

一些注意事项:

  • 无需创建arr元素的等效整数的新数组,只需在需要时将它们转换为整数。
  • 通过使用Enumerable#each_with_object创建一个空数组,您可以避免在开头添加a = [],在方法结尾处添加行a
  • 您可以改为编写arr[1..-1].each_with_object([arr.first]) do |e,a|,但只需从数组a为空开始就更容易。
  • 如果要插入的元素大于或等于a中已有的所有元素,a.index { |f| ei < f }将返回nil,因此表达式变为i = a.size ,在这种情况下,Array#insert会将元素追加到a。或者,你可以写:

    i = a.index { |f| j < f } 
    i ? a.insert(i,j) : a << j