Ruby 将fixnum与nil进行比较失败,值不是nil
我正在编写一个程序,它接受一个数组和数组中某个值的索引,然后找到最大的最接近的数字(如果左侧有优先权)。然而,我似乎不能调试我的程序的一部分,因为我的逻辑,甚至输出似乎有价值,但当它运行时,它给出了一个错误,即Fixnum不能与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
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