簡體   English   中英

有人可以解釋為什么這不起作用嗎? 有時我得到零

[英]Can someone please explain why this doesn't work? sometimes I get nil

所以我正在解決這些練習問題,也許有更好的方法來做到這一點,但這就是我得到的。 我很困惑為什么這只有時似乎有效......

def nearest_larger(arr, idx)
bigs = []

arr.each do |num|
    if num > arr[idx]
      bigs << num
    end
end

sorted = bigs.sort
    if sorted.length > 1
      sorted = sorted[0]
    end

return arr.index(sorted)
end

puts nearest_larger([2, 3, 4, 8], 2) #DOES NOT WORK
puts nearest_larger([2, 3, 4, 8], 2) #DOES WORK
puts nearest_larger([8, 8, 4, 2], 2) #ALSO WORKS... why?!!!

我不清楚這個函數到底應該做什么,因為我不知道你在做什么,但我看到的最明顯的問題是你有時檢查另一個數組的數組,有時檢查它用於實際元素。 特別是可疑塊是if sorted.length > 1; sorted = sorted[0]; end if sorted.length > 1; sorted = sorted[0]; end if sorted.length > 1; sorted = sorted[0]; end

在您的第一個不起作用的調用中,只有一個數字大於索引2 ,即 8。在這種情況下sorted的長度僅為1 - 因此它不會將其從數組更改為第一項到期到你的 if 語句。

無論如何,第二種情況也不應該起作用。

代碼的稍微修改的工作版本如下。

def nearest_larger(arr, idx)
  larger_numbers = []

  arr.each do |num|
    if num > arr[idx]
      larger_numbers << num
    end
  end

  smallest_larger_number = larger_numbers.sort()[0]

  return arr.index(smallest_larger_number)
end

較小的版本是這樣的:

def nearest_larger(arr, idx)
  arr.index(arr.select {|num| num > arr[idx]}.sort()[0])
end

給定的陣列a和數組索引i ,假設idxa是索引數組ja為其中a[j] > a[i] 如果idxa為空,則返回nil 否則問題是在idxa找到一個索引k ,其中(ki).abs是最小值。 如果idx包含多個索引k其中(ki).abs是最小值,則可以返回這些索引中的任何一個。

選擇索引並找到最接近的

這是解決問題的一種簡單但不是特別有效的方法。

def nearest_larger(arr, idx)
  v = arr[idx]
  a = arr.each_index.select { |i| arr[i] > v }
  return nil if a.empty?
  a.min_by { |i| (i-idx).abs }
end

test = [
  [[2, 3, 4, 8], 2],
  [[8, 5, 4, 3], 2],
  [[8, 3, 4, 2], 2],
  [[8, 5, 8, 2], 2]
]

test.each do |arr, idx|
  i = nearest_larger(arr, idx)
  puts "#{arr} idx = #{idx}: closest idx = #{i.nil? ? "nil" : i}"
end
[2, 3, 4, 8] idx = 2: closest idx = 3
[8, 5, 4, 3] idx = 2: closest idx = 1
[8, 3, 4, 2] idx = 2: closest idx = 0
[8, 5, 8, 2] idx = 2: closest idx = nil

讓我們檢查這些arridx值的步驟:

arr = [8, 5, 4, 3]
idx = 2

v = arr[idx]
  #=> 4 
e = arr.each_index
  #=> #<Enumerator: [8, 5, 4, 3]:each_index> 

正如您看到的Array#each_index方法,當在arr調用時返回一個枚舉器。 將其視為產生價值的機器。 我們可以將枚舉器轉換為數組以查看它們將生成什么值:

e.to_a
  #=> [0, 1, 2, 3]

繼續,

a = e.select { |i| arr[i] > v }
  #=> [0, 1]

e將元素傳遞給Enumerable#select ,后者又傳遞給塊,將塊變量i分配給它們的值。 其實我們可以寫

ee = e.select
  #=> #<Enumerator: #<Enumerator: [8, 5, 4, 3]:each_index>:select> 
ee.to_a
  #=> [0, 1, 2, 3] 
a = ee.each { |i| arr[i] > v }
  #=> [0, 1] 

ee可以被認為是一個復合枚舉器。 如果最后一點令人困惑,請暫時忘記它。

繼續,

return nil if a.empty?

a不為空,所以我們不返回。 最后一步如下。

a.min_by { |i| (i-idx).abs }
  #=> 1 

參見Enumerable#min_by

請注意,我可以用arr.size.times (參見Integer#times )或0.up_to(arr.size-1) (參見Integer#upto )替換arr.each_index

檢查任一側然后移出一個直到找到更大的值

我們可以以增加復雜性為代價來提高效率。 事實上,下面的代碼不是很像 Ruby 並且 imo 相當沒有吸引力。

def nearest_larger(arr, idx)
  v = arr[idx]
  last = arr.size-1
  iup, idn = idx + 1, idx - 1
  while iup <= last || idn >= 0
    if iup <= last
      return iup if arr[iup] > v
      iup += 1
    end
    if idn >= 0
      return idn if arr[idn] > v
      idn -= 1
    end
  end
  nil
end

test.each do |arr, idx|
  i = nearest_larger(arr, idx)
  puts "#{arr} idx = #{idx}: closest idx = #{i.nil? ? "nil" : i}"
end
[2, 3, 4, 8] idx = 2: closest idx = 3
[8, 5, 4, 3] idx = 2: closest idx = 1
[8, 3, 4, 2] idx = 2: closest idx = 0
[8, 5, 8, 2] idx = 2: closest idx = nil

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM