根据另一个数组修改数组中的哈希值

时间:2015-06-24 18:46:00

标签: arrays ruby hash

我有两个这样的数组:

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)

我该如何解决这个问题?

4 个答案:

答案 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.length2,因此在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"]}

那样访问它们