繁体   English   中英

Ruby - 如何将数据添加到嵌套数组中?

[英]Ruby - How do you add data into a nested array?

我对 Ruby 比较陌生,我正在尝试设计一个有助于我工作的代码。

我希望代码做的是允许用户从星期一开始输入一周中每一天的“发票号码”,然后当用户输入完发票号码后,程序应该询问工作了多少小时每天。 然后,我希望程序将工作小时数除以每天输入的发票数量和 output 的“计费时间”,格式如下:

假设星期一工作了 10 个小时,您输入了发票 #123 和 #124

该程序应为 output 以下 -

Monday
#123 - 5 Hours
#124 - 5 Hours 

但我希望一周中的每一天都发生这种情况。 我假设我需要使用嵌套数组,但我只是对如何 go 关于添加来自用户的条目以及让程序知道何时“移动”到第二天添加下一组感到困惑的条目。

这是我到目前为止的代码:

days = ["Mon","Tue","Wed","Thurs","Fri","Sat","Sun"]
entry = Array.new
days.each do |day|
    while entry != "ok"
      puts "Enter PR # for " + day
      puts "/n Type 'ok' when finished"
      entry.each do |input|
        input << gets.to_s.chomp
      end
    end
end

本质上,我只想让程序通过键入“ok”或其他内容来识别用户已完成输入当天的条目,以便它可以从星期一移动到星期二等。

在一个完美的世界中......在序列的最后,我希望程序将每天所有类似命名的发票编号的值组合成一个结果(即如果发票 #123 在星期一和星期二应用,则程序将这两天的计费小时数和 output 结果相加为一个总计费金额。)

预先感谢您对此提供的任何帮助,因为随之而来的知识将受到高度重视!

嘿 - 你在这里 go -> https://gist.github.com/Oluwadamilareolusakin/4f16cfbbfbf717c51188/4f16cfbbf717c

为你做了一个可能有帮助的要点,让我知道!

注意:注意while true ,以免陷入无限循环

这是为了方便参考:

# frozen_string_literal: true
def display_billable_hours(entries)
  entries.each do |key, value|
    puts "#{key}:"
    puts value
  end
end

def handle_input
  days = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]
  entries = {}

  days.each do |day|

    loop do
      p "Enter your invoice number for #{day}:"
      invoice_number = gets.chomp

      break if invoice_number.length > 0
    end

    loop do
      p "How many hours did you work on #{day}?:"
      hours_worked = gets.chomp
      break if hours_worked.length > 0
    end

    entries[day] = "##{invoice_number} - #{hours_worked} Hours"
  end
  
  entries
end

def do_audit
  entries = handle_input
  display_billable_hours(entries)
end

do_audit

您可以按如下方式收集所需信息。

DAYS = ["Mon", "Tue", "Wed", "Thurs", "Fri", "Sat", "Sun"]
def invoices_by_day
  DAYS.each_with_object({}) do |day, inv_by_day|
    prs = []
    loop do
      puts "Enter PR # for #{day}. Press ENTER when finished"
      pr = gets.chomp
      break if pr.empty?
      prs << pr
    end
    hours =
      if prs.any?
        puts "Enter hours worked on #{day}"
        gets.to_f
      else
        0
      end
    inv_by_day[day] = { prs: prs, hours: hours }
  end
end

认为

h = invoices_by_day
  #=> { "Mon"=>{ prs: ["123", "124"], hours: 21.05 },
  #     "Tue"=>{ prs: ["125"], hours: 31.42 },
  #     "Wed"=>{ prs: ["126", "127"], hours: 68.42 },
  #     "Thu"=>{ prs: ["128"], hours: 31.05 },
  #     "Fri"=>{ prs: [], hours: 0 },
  #     "Sat"=>{ prs: ["129", "130"], hours: 16.71 }
  #     "Sun"=>{ prs: ["131"], hours: 55.92 } }

然后您可以通过各种方式显示此信息,如下所示。

h.each do |day, g|
  puts day
  if g[:prs].empty?
    puts "  No invoices"
  else
    avg = (g[:hours]/g[:prs].size).round(2)
    g[:prs].each { |pr| puts "  ##{pr}: #{avg}" }
  end
end
Mon
  #123: 10.53
  #124: 10.53
Tue
  #125: 31.42
Wed
  #126: 34.21
  #127: 34.21
Thurs
  #128: 31.05
Fri
  No invoices
Sat
  #129: 8.36
  #130: 8.36
Sun
  #131: 55.92

作为一项规则,将数据收集与数据处理和结果呈现分开是一种很好的做法。 这使得以后更容易更改。

我使用Kernel#loop with break进行几乎所有循环。 loop的一个优点是使用块(与whileuntil不同),将块内创建的局部变量的 scope 限制在块中。 另一个优点是它通过跳出循环来处理StopIteration异常。 当枚举器尝试生成超出其最后一个值的元素时,会引发该异常。 例如,如果e = 3.times #=> #<Enumerator: 3:times> ,则e.next #=> 0 , e.next #=> 1 e.next #=> 2 , e.next #=> StopIteration

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM