【问题标题】:Can't convert nil into string--Ruby Secret Santa无法将 nil 转换为字符串——Ruby Secret Santa
【发布时间】:2023-03-24 15:36:02
【问题描述】:

我编写了一个秘密圣诞老人程序(ala Ruby Quiz...ish),但偶尔在程序运行时,我会收到错误消息。 统计:如果底池中有 10 个名字,错误出现的概率约为 5%。如果底池中有 100 个名字,则不到 1%。这是在 bash 中进行 1000 次试验。我已经确定礼物数组在某个时候为零,但我不确定为什么或如何避免它。 提供代码...

0.upto($lname.length-1).each do |i|
  j = rand($giftlname.length) # should be less each time.
  while $giftlname[j] == $lname[i] # redo random if it picks same person
    if $lname[i] == $lname.last # if random gives same output again, means person is left with himself; needs to switch with someone
      $giftfname[j], $fname[i] = $giftfname[i], $fname[j]
      $giftlname[j], $lname[i] = $giftlname[i], $lname[j]
      $giftemail[j], $email[i] = $giftemail[i], $email[j]
    else
       j = rand($giftlname.length)
    end
  end
  $santas.push('Santa ' + $fname[i] + ' ' + $lname[i] + ' sends gift to ' + $giftfname[j] + ' ' + $giftlname[j] + ' at ' + '<' + $giftemail[j] + '>.') #Error here, something is sometimes nil
  $giftfname.delete_at(j)
  $giftlname.delete_at(j)
  $giftemail.delete_at(j)
end

谢谢!

【问题讨论】:

  • 只是出于好奇,为什么在所有变量名前都使用 $?在 Ruby 中,这使它们成为全局变量,这几乎不是您想要的。
  • 我本来是把它写成一个新的方法,是为了避免把所有的变量都带进去。后来发现不需要用的时候,我把这个方法去掉,做成一个平面程序递归......但我从来没有拿出 $s。
  • 在 ruby​​ 中,您应该从不需要使用全局变量。我会在没有任何 $ 的情况下首先重写它。红宝石的部分美丽之处在于到处都没有“$”。 (我什至不确定为什么它甚至不再受支持)

标签: ruby arrays string null


【解决方案1】:

我认为你的问题就在这里:

$giftfname[j], $fname[i] = $giftfname[i], $fname[j]

您的i 值介于零到$fname(含)中的最后一个索引之间,并且可能您的$giftfname$fname 的克隆开始(或至少另一个带有 的数组长度相同)。但是,当您在each 中旋转时,您正在缩小$giftfname,因此$giftfname[i] 将变为nil,并且上面的交换操作会将nil 放入$giftfname[j](这应该是一个有用的条目$giftfname)。类似的问题适用于$giftlname$giftemail

我建议使用一个包含三个元素对象(名字、姓氏、电子邮件)的数组,而不是您的三个并行数组。 Array 上还有一个 shuffle 方法可能对您有用:

  • 从一群人开始。
  • 复制该数组。
  • 随机复制副本,直到它在原始数组的每个索引处都不同。
  • 然后zip 一起获得最终的给予者/接受者对列表。

【讨论】:

  • 是的,我明白了。有趣的是,在我设计出一个效果更好的之前,我暂时坚持使用它是一个任意的洗牌器。是时候设计一个更好的了。
  • @podopie:我添加了一些关于更好方法的提示(至少对于小列表)。
  • 我还没有开始尝试您的解决方案,但我在重置数组克隆后使用了重试语句(放弃了那里的随机播放)。我是编程新手,那么对于这样的子句,Ruby 世界可以接受重试语句吗?还是懒人的出路?谢谢!
  • @podopie:我认为retry 是处理意外或异常情况的工具。使用retry 进行正常的流量控制对我来说有点难闻。恕我直言,当然。
【解决方案2】:

想通了并使用了重试语句。 if 语句现在看起来像这样(所有其他变量也被编辑为非全局变量)

if lname[i] == lname.last 
  santas = Array.new
  giftfname = fname.clone
  giftlname = lname.clone
  giftemail = email.clone
  retry  

除了一些其他编辑之外,它创建了我需要的解决方案,而无需再次过多地分解代码。肯定也会尝试 mu 的解决方案,但我很高兴我现在运行没有错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 2012-07-15
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 2010-10-13
    相关资源
    最近更新 更多