在字符串中枚举

Enumerate inside a string

我正在尝试枚举字符串内的数组,并在字符串内插入数组的值。

示例:

todos = ["sleep", "eat", "powernap"]

"Today I have todo: \n" +
'#{todos.each do |todo| }'
"\t #{todo}" +
'#{end}'

输出:

"Today I have todo: \n\tsleep\neat\npowernap"

您期望 #{...} 像 ERB 的 <%...%> 甚至 PHP 的 <?php 一样工作,但事实并非如此。字符串插值必须包含一个完整的、语法上有效的 Ruby 表达式,而那段代码是不完整的。

您可以将其修改为单数表达式:

"Today I have todo: #{todos.join("\t "}"

或者您可以手动进行迭代,尽管这在性能方面通常 sub-optimal:

todos.each_with_object("Today I have todo:") do |todo, buffer|
  buffer << "\t " << todo
end

如您所见,第一个版本明显更加简洁。

Ruby 的字符串插值选项非常灵活,但它们确实要求代码为 self-contained.

我假设你想要这个:

Today I have todo:
        sleep
        eat
        powernap

为此,您可以使用 map to wrap each element in a tab and newline, then join 将数组中的字符串变成单个字符串。

todos.map {|todo| "\t#{todo}\n"}.join("")

这将在每个元素周围放置一个换行符和制表符,然后将每个元素连接在一起。请注意,它通过使用 #{} 在字符串中嵌入变量来使用串联。也可能是 "\t" + todo + "\n",完全一样。

结果是:

"\tsleep\n\teat\n\tpowernap\n"

然后你可以将它与字符串连接起来,不需要什么特别的。

puts "Today I have todo:\n" +
     todos.map {|todo| "\t#{todo}\n"}.join("") +
     "I hope I get them done!\n"

有很多方法可以做到这一点,但重要的是它必须产生一个字符串。 each 不会工作,因为它会产生一个数组,你会得到这样的东西:

Today I have todo:
    ["sleep", "eat", "powernap"]
I hope I get them done!

如果您愿意,可以通过将整个表达式放入字符串内的 #{} 来将其作为字符串插值来执行。这是一个将列表转换为 comma-separated 字符串的简单示例。

puts "Today I have todo: #{todos.join(", ")}\n"

任何表达式都可以进入#{},但#{}必须包含完整的表达式!每个 #{} 将单独 运行,每个结果将连接到字符串中。