如何将这个 Ruby 字符串转换为一个数组?

5
什么是将以下Ruby字符串转换为数组的最佳方法(我使用ruby 1.9.2 / Rails 3.0.11)?
Rails控制台:
>Item.first.ingredients
=> "[\"Bread, whole wheat, 100%, slice\", \"Egg Substitute\", \"new, Eggs, scrambled\"]"
>Item.first.ingredients.class.name
=> "String"
>Item.first.ingredients.length
77

期望的输出结果:

>Item.first.ingredients_a
["Bread, whole wheat, 100%, slice", "Egg Substitute", "new, Eggs, scrambled"]
>Item.first.ingredients_a.class.name
=> "Array
>Item.first.ingredients_a.length
=> 3

例如,如果我这样做:

>Array(Choice.first.ingredients)

I get this:

=> ["[\"Bread, whole wheat, 100%, slice\", \"Egg Substitute\", \"new, Eggs, scrambled\", \"Oats, rolled, old fashioned\", \"Syrup, pancake\", \"Water, tap\", \"Oil, olive blend\", \"Spice, cinnamon, ground\", \"Seeds, sunflower, kernels, dried\", \"Flavor, vanilla extract\", \"Honey, strained/extracted\", \"Raisins, seedless\", \"Cranberries, dried, swtnd\", \"Spice, ginger, ground\", \"Flour, whole wheat\"]"] 

我相信必然有明显的方法来解决这个问题。
为了清晰起见,此内容将在表单的文本区域中进行编辑,因此应尽可能使其更加安全。

1
最好的方法是修改“ingredients”方法。 - Mark Thomas
1
如果您无法更改配方方法,那么您至少应该将其发布,以便我们可以看到其输出内容。覆盖它肯定是一个选项,但我们必须先看一下才能提供帮助。 - Mark Thomas
6个回答

9
您所拥有的内容看起来像是JSON格式,您可以采取以下方式操作:
JSON.parse "[\"Bread, whole wheat, 100%, slice\", \"Egg Substitute\", \"new, Eggs, scrambled\"]"
#=> ["Bread, whole wheat, 100%, slice", "Egg Substitute", "new, Eggs, scrambled"]

这样做可以避免使用 eval 带来的很多问题。

虽然你应该认真思考为什么要首先将数据存储为这种形式,并考虑更改它,这样就不必进行此操作了。此外,很可能应该将其解析为一个数组,在 ingredients 中,使方法返回更有意义的内容。如果你几乎总是对方法的返回值执行相同的操作,则该方法是错误的。


只有当它确实是JSON时,我才会这样做。只有查看“ingredients”方法才能确定。 - Mark Thomas
@MarkThomas 完全同意,但是关于为什么数据以它所在的字符串格式存在并没有提供太多信息,所以(不幸的是)我们必须做出假设。 - Andrew Marshall

5
class Item
  def ingredients_a
    ingredients.gsub(/(\[\"|\"\])/, '').split('", "')
  end
end
  1. 去掉多余字符
  2. 使用分隔模式将其拆分为数组元素

我真的很喜欢JSON.parse的答案,但这个应该可以工作,并且可能是解决问题最直接的方法。 - Nathan W
2
+1 这是对问题最直接的回答。一个优雅的回答需要更多关于数组如何首先变成字符串的信息。 - Mark Thomas

1

看起来ingredients方法返回结果数组的.inspect输出。这种输出方式并不是很有用。您是否有能力将其更改为返回普通数组?

我不会使用eval,因为它只会增加已经混乱的代码的混乱程度。


我同意你的想法,尽可能避免使用'eval'。如果必要的话,我可以潜在地覆盖该方法或进行其他调用,但我仍然有一个问题,即如何最好地将字符串转换为数组,因为数据类型可能不会改变。我可以潜在地将数据存储在可序列化的文本字段中,并以某种格式存储数组。 - Nathan W
@NathanW 我认为问题在于,为什么你的数组一开始就是字符串形式? - Andrew Marshall
+1 虽然这更像是一条评论,但在有限的信息下,它非常接近可能的正确答案。 - Andrew Marshall
@andrew,我正在允许通过表单中的文本区编辑数组。这个示例展示了信息通过参数传递的方式。如果有其他更好的方法来维护数组,那就非常好,请告诉我。 - Nathan W
@NathanW 那我假设正在发送的是 JSON?如果不是,那就应该是。 - Andrew Marshall

1

就像Mark Thomas所说的那样,修改你的ingredients方法,除非你真的想要分别返回一个字符串和一个数组的两个不同方法。我假设你只想返回一个数组。为了论证,假设你的ingredients方法当前返回一个名为ingredients_string的变量。请按照以下方式修改你的方法:

def ingredients
  ...
  ingredients_array = ingredients_string.split('"')
  ingredients_array.delete_if { |element| %(", "[", "]").include? element }
  ingredients_array
end

1
就记录而言,我认为安德鲁·马歇尔的JSON.parse建议更加优雅。 - Michael Stalker

0
如果您的字符串数组是标准的JSON格式,只需使用JSON.parse()即可。

0

是的,我想我可以将数据存储到可序列化的数组字段中,但我仍然从一个看起来像上面格式的字符串开始 :)..所以需要将其转换为数组才能将其放入其中 :). - Nathan W

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接