我有一个文件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)
如何向数组添加哈希?
答案 0 :(得分:3)
您误解了readlines
和read
正在做什么,以及您的文件内容。让我们从这些事情开始:
File.read
将文件内容读入字符串。File.readlines
将文件内容读入包含字符串的数组,其中每个字符串都是文件的一行。它(大致)等同于File.read('filename.txt').split("\n")
。因此,请考虑您的文件,其中包含(更正为有效的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数组,你可以按照你期望的方式添加另一个哈希。