如何将哈希插入数组

时间:2016-01-02 20:51:51

标签: arrays ruby

我有一个文件file.txt,它有一个数组,其中包含哈希:

[{:name "Muhammad"},{:name "Mahmoud"}]

我试图通过以下方式阅读:

$list = File.readlines('file.txt')

然后我将hash添加到数组中:

$list << hash

代码有效,但它在数组中创建了一个数组:

["[{:name "/Mohammed/"},{:name "/Mahmoud/"}]"{:name "Ahmed"}]

当我用:

读取文件时
$list = File.read('file.txt')

然后将hast [sic]添加到数组中:

$list << hash

我实际上将hash添加到数组中:

$list << hash

它给出了这个错误:

can't convert Hash into String (TypeError)

如何向数组添加哈希?

1 个答案:

答案 0 :(得分:3)

您误解了readlinesread正在做什么,以及您的文件内容。让我们从这些事情开始:

  1. 文件不包含数组或散列 - 它们包含可能被解析为数组或散列的文本。
  2. File.read将文件内容读入字符串。
  3. File.readlines将文件内容读入包含字符串的数组,其中每个字符串都是文件的一行。它(大致)等同于File.read('filename.txt').split("\n")
  4. 因此,请考虑您的文件,其中包含(更正为有效的Ruby语法)

    [{name: "Muhammad"},{name: "Mahmoud"}]
    

    虽然它看起来像一个包含哈希的数组,但括号没有语义含义。让我们读一读:

    > data = File.read('file.txt')
     => "[{name: \"Muhammad\"},{name: \"Mahmoud\"}]\n"
    

    请注意以下几点:

    • 您的数据周围有引号 - 它是一个字符串
    • 您文件中的引号("Muhammad")已转义
    • 字符串末尾有\n,表示换行符

    我们可以问data它是什么,我们可以打印它以确定它确实是您的文件内容而没有任何转义:

    > data.class
     => String
    > puts data
    [{name: "Muhammad"},{name: "Mahmoud"}]
     => nil
    

    现在让我们试试File.readlines

    > lines = File.readlines('file.txt')
     => ["[{name: \"Muhammad\"},{name: \"Mahmoud\"}]\n"]
    

    围绕我们之前使用的相同字符串的注意括号。这是一个包含单个字符串的数组,该字符串是文件中的第一行(唯一)。

    > lines.class
     => Array
    > lines.size
     => 1
    > puts lines.first
    [{name: "Muhammad"},{name: "Mahmoud"}]
     => nil
    > lines.first == data
     => true
    

    现在我们可以看到您所看到的错误。当您使用readlines然后添加hash时,您正在向数组添加哈希。这在Ruby中是完全合法的,因为您可以拥有包含不同类型元素的数组。当您添加hash时,您最终得到了一个包含字符串和散列的数组。

    > hash = {name: "Ahmed"}
     => {:name=>"Ahmed"}
    > lines << hash
     => ["[{name: \"Muhammad\"},{name: \"Mahmoud\"}]\n", {:name=>"Ahmed"}]
    > lines.map(&:class)
     => [String, Hash]
    > lines.size
     => 2
    

    但是,当您尝试将哈希添加到read的结果时,您正在向字符串添加哈希值,Ruby不会这样做。

    > data << hash
    TypeError: no implicit conversion of Hash into String
    

    因此,为了回答您的标题问题,您可以向数组添加哈希,您只是没有意识到您拥有,并且您的数组最初并未包含您期望的数据。

    要以包含哈希的Ruby数组的形式读取文件,可以使用eval,它执行包含Ruby代码的字符串。这通常是不可取的,因为例如,如果您在其他人提供的数据上运行它,它可能包含您并不真正想要执行的代码。由于您控制此文件并且它是您自己的数据,因此在这种情况下它足够安全。

    > real_data = eval(File.read('file.txt'))
     => [{:name=>"Muhammad"}, {:name=>"Mahmoud"}]
    > real_data.class
     => Array
    > real_data.first
     => {:name=>"Muhammad"}
    > real_data << hash
     => [{:name=>"Muhammad"}, {:name=>"Mahmoud"}, {:name=>"Ahmed"}]
    

    现在你有一个包含Ruby哈希的Ruby数组,你可以按照你期望的方式添加另一个哈希。