是否可以在 Ruby 中使用多维数组?

Is it possible to have multidimensional arrays in Ruby?

我有一个数组,用于在我的应用程序中存储被禁止的 IP 地址:

bannedips = ["10.10.10.10", "20.20.20.20", "30.30.30.30"]

我想为每个禁止的 IP 地址添加更多信息(IP 地址、禁止时间戳、禁止原因)。

如何在 Ruby 中执行此操作?

在Ruby中,多维数组只是数组的数组:

bannedips = [["10.10.10.10", "more data", "etc"], ["20.20.20.20", ...]]

更好的方法是使用哈希数组,这样您就可以标记值:

bannedips = [{ip: "10.10.10.10", timestamp: 89327414}, ...]

是的,多维数组在Ruby中是可能的。数组可以包含任何值,因此多维数组只是一个包含其他数组的数组:

banned_ips = [
  ["10.10.10.10", Date.new(2015, 1, 2),   "reason"],
  ["20.20.20.20", Date.new(2014, 12, 28), "reason"],
  ["30.30.30.30", Date.new(2014, 12, 29), "reason"],
]

尽管我个人不建议为此目的使用多维数组。相反,创建一个 class 来封装有关被禁止 IP 的信息。

简单示例:

class BannedIP
  attr_reader :ip, :time, :reason

  def initialize(ip, time:, reason: "N/A")
    @ip = ip
    @time = time
    @reason = reason
  end
end

banned_ips = [
  BannedIP.new("10.10.10.10", time: Date.new(2015, 1, 2)),
  BannedIP.new("20.20.20.20", time: Date.new(2014, 12, 28)),
  BannedIP.new("30.30.30.30", time: Date.new(2014, 12, 29), reason: "Spam"),
]    

如果要跟踪的 IP 数量合理,我可能会使用简单的哈希:

banned_ips = {
  "10.10.10.10" => {:timestamp => Time.now, :reason => 'foo'},
  "20.20.20.20" => {:timestamp => Time.now, :reason => 'bar'},
  "30.30.30.30" => {:timestamp => Time.now, :reason => nil}
}

散列是一种创建类似于索引数据库的列表的快速而肮脏的方法;查找速度非常快。而且,由于您只能拥有特定键的单个实例,因此可以避免处理重复数据:

banned_ips["20.20.20.20"] # => {:timestamp=>2015-01-02 12:33:19 -0700, :reason=>"bar"}
banned_ips.keys # => ["10.10.10.10", "20.20.20.20", "30.30.30.30"]

作为选择数组与散列的一般编程技巧。如果你:

  • 必须快速访问特定值,使用散列,其作用类似于随机访问数据库。
  • 想要一个队列或您将顺序访问的值列表,然后使用数组。

因此,对于您想要的检索与特定 IP 关联的值,请使用散列。数组或数组的数组会导致代码浪费时间寻找特定值,并且由于这些查找而将新项目添加到数组时速度会变慢。

在某种程度上,将此类信息存储到数据库中变得更加明智,作为开发人员,了解它们是件好事。它们是我们工具箱中需要的众多工具之一。