Ruby 将fixnum与nil进行比较失败,值不是nil

Ruby 将fixnum与nil进行比较失败,值不是nil,ruby,debugging,Ruby,Debugging,我正在编写一个程序,它接受一个数组和数组中某个值的索引,然后找到最大的最接近的数字(如果左侧有优先权)。然而,我似乎不能调试我的程序的一部分,因为我的逻辑,甚至输出似乎有价值,但当它运行时,它给出了一个错误,即Fixnum不能与nil相比,我不知道为什么。任何帮助都将不胜感激 def nearest_larger(arr, idx) i = idx until arr[i] > arr[idx] || i == 0 i -=1 end le

我正在编写一个程序,它接受一个数组和数组中某个值的索引,然后找到最大的最接近的数字(如果左侧有优先权)。然而,我似乎不能调试我的程序的一部分,因为我的逻辑,甚至输出似乎有价值,但当它运行时,它给出了一个错误,即Fixnum不能与nil相比,我不知道为什么。任何帮助都将不胜感激

def nearest_larger(arr, idx)
    i = idx
    until  arr[i] > arr[idx] || i == 0
        i -=1
    end
    left = arr[i]
    lefti = i
    i = idx
    puts arr[idx] #4
    puts arr[i] #4 (functions as nil in next line)
    until (arr[idx] < arr[i]) || (i == arr.length)
        i += 1
    end
    right = arr[i]
    righti = i
    puts righti
    if  righti == arr.length && lefti == 0
        return nil
    elsif right == left
        return lefti
    elsif right < left
        return lefti
    elsif right > left
        return righti
    else
        print "idk man"
    end
end

nearest_larger([2,8,4,3], 2)
def最近的_较大值(arr、idx)
i=idx
直到arr[i]>arr[idx]|i==0
i-=1
结束
左=arr[i]
左i=i
i=idx
放置arr[idx]#4
放置arr[i]#4(在下一行中用作nil)
直到(arr[idx]左
返回右侧
其他的
打印“idk人”
结束
结束
最接近的_较大([2,8,4,3],2)
--错误消息--

将Fixnum与nil进行比较失败


(回复):11:在`中使用
to_i
,将
nil
转换为
0
-

   def nearest_larger(arr, idx)
     i = idx
     until  arr[i].to_i > arr[idx].to_i || i.to_i == 0
      i -=1
     end
     left = arr[i]
     lefti = i
     i = idx
     puts arr[idx] #4
     puts arr[i] #4 (functions as nil in next line)
     until (arr[idx].to_i < arr[i].to_i) || (i.to_i == arr.length)
      i += 1
     end
     right = arr[i]
     righti = i
     puts righti
     if  righti.to_i == arr.length && lefti.to_i == 0
       return nil
     elsif right == left
       return lefti
     elsif right.to_i < left.to_i
      return lefti
     elsif right.to_i > left.to_i
      return righti
     else
      print "idk man"
     end
   end

   nearest_larger([2,8,4,3], 2)
def最近的_较大值(arr、idx)
i=idx
直到arr[i].to_i>arr[idx].to_i | i.to_i==0
i-=1
结束
左=arr[i]
左i=i
i=idx
放置arr[idx]#4
放置arr[i]#4(在下一行中用作nil)
直到(arr[idx].to_ileft.to_i
返回右侧
其他的
打印“idk人”
结束
结束
最接近的_较大([2,8,4,3],2)

正如@Amit已经回答了您的问题,我想向您展示一种方法(在众多方法中),您可以使您的方法更像Ruby,这在一定程度上意味着减少对索引的依赖。我将用一个例子来解释这一点

arr = [2, 8, 4, 7, 3, 8, 5, 9]
idx = 3
如您所见,我们希望最接近的较大值为:

target = arr[3]
  #=> 7
答案是
8
。让我们找到最接近的较高值的索引(当然,它会给出该值)

我将给出的答案不是最好的方法,但我选择它是因为,通过详细介绍它,您将了解很多关于Ruby的知识

通常,当问题涉及索引时,您首先要做的是写:

arr.each_with_index
  # => #<Enumerator: [2, 8, 4, 7, 3, 8, 5, 9]:each_with_index>
如您所见,
enum
是一个枚举器,这意味着它是类的一个实例

我们可以将此枚举数转换为数组,如下所示:

pairs = enum.to_a
  #=> [[2, 0], [8, 1], [4, 2], [7, 3], [3, 4], [8, 5], [5, 6], [9, 7]]
mx = [before.size, after.size].max
  #=> 4
if before.size < mx
  before.concat [[target, nil]]*(mx-before.size)
elsif after.size < mx
  after.concat [[target, nil]]*(mx-before.size)
end
before
  #=> [[4, 2], [8, 1], [2, 0], [7, nil]] 
after
  #=> [[3, 4], [8, 5], [5, 6], [9, 7]]
但是,请稍候,类
枚举器
没有方法
:to_a
。这意味着它是从
枚举器的祖先之一继承的,这些祖先是:

Enumerator.ancestors
  #=> [Enumerator, Enumerable, Object, Kernel, BasicObject] 
我们可以(按顺序)查看以下内容:
:to_a
,但更直接的方法是:

enum.method(:to_a).owner
  #=> Enumerable
果然是这样

这是一种消遣,但现在让我们使用上面的数组
对。顺便说一句,您通常只写:

pairs = arr.each_with_index.to_a
而不是像
enum
这样的中间变量

pairs
的美妙之处在于,通过操纵其元素(两个元素数组),
arr
的每个元素的索引都与元素本身一起携带

试试这个:

before = (idx.zero? ? [] : pairs[0..idx-1]).reverse
  #=> [[4, 2], [8, 1], [2, 0]] 
after  = pairs[idx+1..-1]
  #=> [[3, 4], [8, 5], [5, 6], [9, 7]] 
解决方案现在就在眼前。我们只想在
之前和
之后逐步遍历
的元素,直到一对中的第一个元素大于
目标#=>7

现在你可能想知道我是否真的简化了这个问题。耐心点。我这样做是为了使用一些Ruby方法。首先,让我们以一种方便的方式组合
之前
之后
,使用。(您正在阅读链接中的方法定义,不是吗?)

在执行此操作之前,可以方便地使
之前
之后
的长度相同。一种方法如下:

pairs = enum.to_a
  #=> [[2, 0], [8, 1], [4, 2], [7, 3], [3, 4], [8, 5], [5, 6], [9, 7]]
mx = [before.size, after.size].max
  #=> 4
if before.size < mx
  before.concat [[target, nil]]*(mx-before.size)
elsif after.size < mx
  after.concat [[target, nil]]*(mx-before.size)
end
before
  #=> [[4, 2], [8, 1], [2, 0], [7, nil]] 
after
  #=> [[3, 4], [8, 5], [5, 6], [9, 7]]
这个数组有四个元素,第一个是
[[4,2],[3,4]]

现在,我们可以使用来获取最接近的较高值的索引:

p = pairs_of_pairs.find { |(b_val,_), (a_val,_)| [b_val, a_val].max > target }
  #=> [[8, 1], [8, 5]]
(暂时忘记我编写块变量的方式。)

因此
p
包含
成对
中的第一个元素,
[b_val,a_val].max>target
计算
true
。如果
arr
中没有大于
target
的值,
p
将等于
nil

由于
p
不是
nil
,所以剩下的就是确定
p
的哪个元素包含的值高于
target
并返回相应的索引。由于领带在
arr
中位于左侧,因此我们首先在
之前检查

i = (p.first.first > target) ? p.first.last : p.last.last
  #=> 1
其值为:

arr[i]
  #=> 8
综上所述,我们可以写:

def nearest_larger(arr, idx)
  target = arr[idx]
  pairs = arr.each_with_index.to_a
  before = (idx.zero? ? [] : pairs[0..idx-1]).reverse
  after  = pairs[idx+1..-1]
  mx = [before.size, after.size].max
  if before.size < mx
    before.concat [[target, nil]]*(mx-before.size)
  elsif after.size < mx
    after.concat [[target, nil]]*(mx-after.size)
  end
  p = before.zip(after).find { |(b_val,_), (a_val,_)|
    [b_val, a_val].max > target }
  p ? ((p.first.first > target) ? p.first.last : p.last.last) : nil
end

nearest_larger(arr, 3)
  #=> 1
nearest_larger(arr, 7)
  #=> nil
find
调用将
对中对的每个元素传递到块中。第一个元素是
[[4,2],[3,4]]
。将值分配给块使用“并行分配”和“消歧”:

我使用下划线(局部变量的有效名称!)来提醒大家注意,我在块计算中没有使用下划线

当它运行时,它给出了一个错误,Fixnum不能与nil进行比较,我不知道为什么

这是因为这个表达:

until (arr[idx] < arr[i]) || (i == arr.length)
返回前面提到的数组。是一种边界检查,它将删除低于
0
或高于数组
大小的所有索引

例如:

adjacent_indices(5, 0) #=> [1, 2, 3, 4]
adjacent_indices(5, 1) #=> [0, 2, 3, 4]
adjacent_indices(5, 2) #=> [1, 3, 0, 4]
adjacent_indices(5, 3) #=> [2, 4, 1, 0]
adjacent_indices(5, 4) #=> [3, 2, 1, 0]
#    0  1  2  3
a = [2, 8, 4, 3]
nearest_larger(a, 0) #=> 1
nearest_larger(a, 1) #=> nil
nearest_larger(a, 2) #=> 1
nearest_larger(a, 3) #=> 2
看起来不错

使用,我们可以很容易地找到第一个索引
i
,其数组值(即
array[i]
)大于索引
n
(即
array[n]
)处的值:

例如:

adjacent_indices(5, 0) #=> [1, 2, 3, 4]
adjacent_indices(5, 1) #=> [0, 2, 3, 4]
adjacent_indices(5, 2) #=> [1, 3, 0, 4]
adjacent_indices(5, 3) #=> [2, 4, 1, 0]
adjacent_indices(5, 4) #=> [3, 2, 1, 0]
#    0  1  2  3
a = [2, 8, 4, 3]
nearest_larger(a, 0) #=> 1
nearest_larger(a, 1) #=> nil
nearest_larger(a, 2) #=> 1
nearest_larger(a, 3) #=> 2
嗨-完全错误m
def adjacent_indices(size, n)
  (1...size).flat_map { |i| [n - i, n + i] }.reject { |i| i < 0 || i >= size }
end
adjacent_indices(5, 0) #=> [1, 2, 3, 4]
adjacent_indices(5, 1) #=> [0, 2, 3, 4]
adjacent_indices(5, 2) #=> [1, 3, 0, 4]
adjacent_indices(5, 3) #=> [2, 4, 1, 0]
adjacent_indices(5, 4) #=> [3, 2, 1, 0]
def nearest_larger(array, n)
  adjacent_indices(array.size, n).find { |i| array[i] > array[n] }
end
#    0  1  2  3
a = [2, 8, 4, 3]
nearest_larger(a, 0) #=> 1
nearest_larger(a, 1) #=> nil
nearest_larger(a, 2) #=> 1
nearest_larger(a, 3) #=> 2