将哈希值插入到字符串中

时间:2013-01-27 07:39:27

标签: ruby arrays string hash insert

我有一系列格式为

的哈希
albums = [ {name: "Sgt. Pepper's Lonely Hearts Club Band", year: "1967" }, 
           { name: "Are You Experienced?", year: "1967" } 
         ]

等。

我试图将此输出插入到需要插入html的字符串中。我目前有这个

def convert_to_html albums
  string_before = 
    "<html>
      <head>
        <title>\"Rolling Stone's ....\"</title>
      </head>
      <body>
        <table>\n" + 
        albums.each do |x| 
          "name is: #{x.values[0]} year is: #{x.values[1]}"
        end  + "
        </table>
      </body>
    </html>"
end

我知道这可能不是获取价值的最佳方法,但我无法想出任何其他方式,但我的主要问题是,当我尝试这个时,我得到了这个错误:

[2013-01-27 00:16:20] ERROR TypeError: can't convert Array into String
    albums.rb:72:in `+'
    albums.rb:72:in `convert_to_html'
    albums.rb:28:in `block in render_list'
    albums.rb:26:in `open'
    albums.rb:26:in `render_list'
    albums.rb:9:in `call'

有没有办法将每个散列的值并排插入字符串?

P.S。我使用名字和年份来提高可读性。我知道#{x.values [0]}#{x.values [1]}是格式化的正确方法。

3 个答案:

答案 0 :(得分:2)

在Ruby中,String#+ 隐式将右操作数转换为字符串。

# like post - oops!
> "hello " + ["world", "moon"]
=> #<TypeError: can't convert Array into String>

# valid, but .. ugly
> "hello " + ["world", "moon"].to_s
=> "hello [\"world\",\"moon\"]"

# likely desired
> "hello " + ["world", "moon"].join(" and ")
=> "hello world and moon"

此外,在帖子albums.each .. do中返回初始数组(专辑)对象,但这仍然是错误的,因为该块的结果被丢弃(使用Array.each执行副作用)。相反,使用albums.map .. do(或albums.collect .. do)来收集/使用块结果。

答案 1 :(得分:0)

这是显示如何操作的简单代码:

album_list = [
  {name: "Sgt. Pepper's Lonely Hearts Club Band", year: "1967" }, 
  { name: "Are You Experienced?", year: "1967" } 
]

def convert_to_html(albums)

"<html>
  <head>
    <title>\"Rolling Stone's ....\"</title>
  </head>
  <body>
    <table>
" + albums.map { |album| 
"     <tr><td>name is: #{ album[:name] } year is: #{ album[:year] }</td></tr>"
}.join("\n") +
"
    </table>
  </body>
</html>"

end

puts convert_to_html(album_list)

哪个输出:

<html>
  <head>
    <title>"Rolling Stone's ...."</title>
  </head>
  <body>
    <table>
    <tr><td>name is: Sgt. Pepper's Lonely Hearts Club Band year is: 1967</td></tr>
    <tr><td>name is: Are You Experienced? year is: 1967</td></tr>
    </table>
  </body>
</html>

在现实生活中,我会使用ERBHAML来生成HTML。它们是很棒的模板工具。

其他写作方式:

<tr><td>name is: #{ album[:name] } year is: #{ album[:year] }</td></tr>"

是:

<tr><td>name is: %s year is: %s </td></tr>" % [ album[:name], album[:year] ] 

或:

<tr><td>name is: %s year is: %s </td></tr>" % album.values_at(:name, :year)

我不建议单独使用album.values,因为它依赖于插入album哈希的顺序。将来,如果您通过在维护代码的同时以不同的顺序放入哈希值来修改哈希值,values顺序将会发生变化,以一种可能不明显的方式打破它。

相反,使用这些访问值的方法之一总是明确地获取与密钥关联的值。这是防御性编程的一部分。

答案 2 :(得分:0)

albums.each没有做你想象的那样。我得到的印象是你希望它沿着这些线附加到你的字符串中。

名字是:Sgt。佩珀的Lonely Hearts Club乐队年份是:1967年 名字是:你有经验吗?年是:1967年

实际发生的事实上没有。在.each中有一个表达式,它与同时尝试将相册数组附加到字符串中的for循环相同。因此无法将Array转换为String错误。

实现所需内容的最简单方法是将字符串放在前面,然后将其附加到字符串中。类似于此的东西。

def convert_to_html albums
append_string = ""
albums.each do |album|
  append_string += "<tr><td>name is: #{album[:name]} year is #{album[:year]} </td></tr>"
end

string_before =
  "<html>
    <head>
      <title>\"Rolling Stone's ....\"</title>
    </head>
    <body>
      <table>\n" + append_string + "
      </table>
    </body>
  </html>"
end