我有两个这样的数组:
a = [{'one'=>1, 'two'=>2},{'uno'=>1, 'dos'=>2}]
b = ['english', 'spanish']
我需要为a
中的每个哈希添加一个键值对来获取此值:
a = [{'one'=>1, 'two'=>2, 'language'=>'english'},{'uno'=>1, 'dos'=>2, 'language'=>'spanish'}]
我试过这个:
(0..a.length).each {|c| a[c]['language']=b[c]}
它不起作用。有了这个:
a[1]['language']=b[1]
(0..a.length).each {|c| puts c}
显示错误:
NoMethodError (undefined method '[]=' for nil:NilClass)
我该如何解决这个问题?
答案 0 :(得分:1)
a.zip(b){|h, v| h["language"] = v}
a # => [
# {"one"=>1, "two"=>2, "language"=>"english"},
# {"uno"=>1, "dos"=>2, "language"=>"spanish"}
# ]
答案 1 :(得分:0)
您遇到的问题是您的(0..a.length)
具有包容性。 a.length = 2
所以您想将其修改为0...a.length
,这是独占的。
另外,你可以像这样使用Array#each_with_index
,这样你就不必担心长度等等。
a.each_with_index do |hash, index|
hash['language'] = b[index]
end
答案 2 :(得分:0)
当each
上的Range
迭代器到达最后一个元素(即a.length
)时,您将尝试访问a
的不存在元素。
在您的示例中,a.length
为2
,因此在each
的最后一次迭代中,您将尝试访问不存在的a[2]
。 (a
只包含索引0和1的2个元素。)a[2]
计算结果为nil
,因此您现在将尝试调用nil['language']=b[2]
,这是{{1}的语法糖1}},由于nil.[]=('language', b[2])
没有nil
方法,因此您获得[]=
。
立即解决方法是不使用独占NoMethodError
迭代a
的结尾:
Range
顺便说一句,您发布的代码:
(0...a.length).each {|c| a[c]['language'] = b[c] }
应明确向您显示您迭代到(0..a.length).each {|c| puts c }
而不是2
。
然而,这只是立即解决的问题。 真正的修复方法是永远不要手动迭代数据结构。这就是迭代器的用途。
像这样的东西,Ruby会跟踪你的索引:
1
或者,根本没有摆弄指数:
a.each_with_index do |hsh, i| hsh['language'] = b[i] end
[注意:最后一个不会改变原始的a.zip(b.zip(['language'].cycle).map(&:reverse).map(&Array.method(:[])).map(&:to_h)).map {|x, y| x.merge!(y) }
和Array
es与其他的不同。]
答案 3 :(得分:0)
这是您可以使用的另一种方法
curl -X PUT
这样做会为 b.each_with_index.with_object(a) do |(lang,i),obj|
obj[i]["language"] = lang
obj
end
#=>[
{"one"=>1, "two"=>2, "language"=>"english"},
{"uno"=>1, "dos"=>2, "language"=>"spanish"}
]
创建一个Enumerator
b
,然后使用[element,index]
作为对象调用with_object
。然后,它迭代a
传递每种语言及其索引以及Enumerator
对象。然后,它使用a
中的索引在b
中查找正确的索引,并将语言键添加到等于语言的哈希值。
请注意,这是一种破坏性方法,a
中的对象会在此过程中发生变异。您可以使用a
使其成为非破坏性的,这将with_object(a.map(&:dup))
a中的哈希值,并且原件将保持不变。
所有这一切我认为dup
更适合这样的任务,但我不确定你的约束是什么。举个例子:
YAML
虽然使用yml = <<YML
-
one: 1
two: 2
language: "english"
-
uno: 1
dos: 2
language: "spanish"
YML
require 'yaml'
YAML.load(yml)
#=>[
{"one"=>1, "two"=>2, "language"=>"english"},
{"uno"=>1, "dos"=>2, "language"=>"spanish"}
]
我会更改数字的结构更像是language =&gt;索引的数字数组,例如YAML
。这样您就可以像{"english" => ["zero","one","two"]}