【问题标题】:How to load a Hash from a File?如何从文件中加载哈希?
【发布时间】:2012-05-05 13:05:00
【问题描述】:

是否有 Ruby 工具可以让我加载格式为 (Abbreviated => Abr) 的缩写文件?然后我需要从另一个文件中读取每个单词。如果单词与缩写词中的单词匹配,我需要将其更改为缩写词。我想我可以使用 Hash,但我不知道如何从文件中加载它。

【问题讨论】:

    标签: ruby hashtable


    【解决方案1】:

    我找到了这个http://www.rubydoc.info/gems/bosh-director/1.1868.0/Bosh%2FDirector%2FConfig.load_hash 在查找了如何自己加载哈希之后。

    我的示例是在 Rails 应用程序中处理 MongoDB 时。

    所以我设置了一个 Initialize 方法来获取我将要使用的集合。

    def initialize @collection = self.class.collection end

    self.class 这里是我所在的类。让我们以 People 为例。

    加载方法如下

    def load_collection(file_path)
      hash_values = self.class.load_hash(file_path)
      @collection.insert_many(hash)
    end
    

    在 binding.pry 中

    [1] pry(#<People>)> file_path
    => "people_results.json"
    [2] pry(#<People>)> hash
    => [{"number"=>0, "first_name"=>"SHAUN", "last_name"=>"JOHNSON", "gender"=>"M", "group"=>"15 to 19", "secs"=>1464}, {"number"=>1, "first_name"=>"TUAN", "last_name"=>"JOHNSON", "gender"=>"M", "group"=>"masters", "secs"=>3994}, {"number"=>2, "first_name"=>"EARLINE", "last_name"=>"BROWN", "gender"=>"F", "group"=>"masters", "secs"=>1415}...
    [3] pry(#<People>)> self
    => #<People:0x007fc80301b5f8 @coll=#<Mongo::Collection:0x70248510355560 namespace=test.people>>
    [4] pry(#<People>)> self.class
    => People
    

    所以在这种情况下,load_hash 方法需要一个参数,在这种情况下,我传入了一个包含一些数据的 json 文件。然后我将该数据插入到我的集合中。

    【讨论】:

      【解决方案2】:

      YAML 是一种非常通用的数据存储格式,可以在应用程序和编程语言之间传输。 JSON 是另一种替代品,在网站中很常见。

      我将 YAML 用于配置文件之类的东西,因为它很容易阅读和修改。例如,这个 Ruby 结构:

      irb(main):002:0> foo = { 'a' => 1, 'b' => [2, 3], 'c' => { 'd' => 4, 'e' => 5 } }
      {
          "a" => 1,
          "b" => [
              [0] 2,
              [1] 3
          ],
          "c" => {
              "d" => 4,
              "e" => 5
          }
      }
      

      转换为 YAML 后如下所示:

      irb(main):003:0> puts foo.to_yaml
      --- 
      a: 1
      b: 
      - 2
      - 3
      c: 
        d: 4
        e: 5
      

      您可以将其保存到文件中:

      File.open('foo.yaml', 'w') { |fo| fo.puts foo.to_yaml }
      

      然后读回:

      bar = YAML.load_file('foo.yaml')
      {
          "a" => 1,
          "b" => [
              [0] 2,
              [1] 3
          ],
          "c" => {
              "d" => 4,
              "e" => 5
          }
      }
      

      同样,使用 JSON:

      puts foo.to_json
      {"a":1,"b":[2,3],"c":{"d":4,"e":5}}
      

      您可以像使用 YAML 一样将 JSON 保存到文件中,然后重新加载它并将其转回散列。虽然语法有点不同:

      irb(main):011:0> File.open('foo.json', 'w') { |fo| fo.puts foo.to_json }
      nil
      irb(main):012:0> bar = JSON.parse(File.read('foo.json'))
      {
          "a" => 1,
          "b" => [
              [0] 2,
              [1] 3
          ],
          "c" => {
              "d" => 4,
              "e" => 5
          }
      }
      

      两者的最大优势在于任何可以读取 YAML 或 JSON 的语言都可以读取这些文件并使用数据,无论是读取还是写入。

      一旦有了散列,就可以很容易地进行字符串替换,因为 Ruby String 的 gsub 可以理解散列。这是来自the docs

      如果第二个参数是一个哈希,并且匹配的文本是它的键之一,那么 对应的值为替换字符串。

      这意味着你可以这样做:

      foo = 'Jackdaws love my giant sphinx of quartz'
      bar = { 'quartz' => 'rosy quartz', 'sphinx' => 'panda' }
      foo.gsub(Regexp.union(bar.keys), bar)
      "Jackdaws love my giant panda of rosy quartz"
      

      在进行替换时,您必须注意字边界冲突,但模式中的 \b 标志可能会有所帮助。完成这项工作是读者的一项练习。

      【讨论】:

      • 虽然这是一个很好的解释,但我认为引入 yaml 或 json 只会使简单的练习复杂化。该文件已经存在,并且已经非常简单 - 一个分隔的文本文件,每行一条记录。只需逐行读取文件,将其拆分,然后构建哈希。
      【解决方案3】:

      参见Marshal.loadMarshal.dump

      此外,您可以考虑将哈希序列化为 yaml 文件,然后通过 YAML 读取/保存。

      【讨论】:

      • Marshal 格式是(或可以是)特定于正在使用的 Ruby 版本的,并且当版本不匹配时,没有(理智的)方法来读取 Marshal 数据。这使得序列化到磁盘的格式不好。
      猜你喜欢
      • 1970-01-01
      • 2010-09-19
      • 2015-07-06
      • 2010-12-19
      • 2013-01-24
      • 2015-07-07
      • 1970-01-01
      • 2012-02-19
      • 2017-05-29
      相关资源
      最近更新 更多