Ruby修改并在哈希数组中添加哈希值

Ruby修改并在哈希数组中添加哈希值,ruby,Ruby,我正在尝试使用collect修改哈希数组。对于每个哈希,我想添加一个新的键/值,并修改一个不同的键/值。但是,我在使用sub修改现有哈希值时遇到问题。它似乎完全用一个数组项替换了散列,该数组项等于sub!命令 paths = [{:path=>"bin/ruby/file1", :tag=>"v_10"}, {:path=>"usr/name/subdir/file2", :tag=>"v_12"}] paths.collect! do |x| x.merge(Ha

我正在尝试使用
collect修改哈希数组。对于每个哈希,我想添加一个新的键/值,并修改一个不同的键/值。但是,我在使用
sub修改现有哈希值时遇到问题。它似乎完全用一个数组项替换了散列,该数组项等于sub!命令

paths = [{:path=>"bin/ruby/file1", :tag=>"v_10"}, {:path=>"usr/name/subdir/file2", :tag=>"v_12"}]

paths.collect! do |x|
  x.merge(Hash[:file => x[:path].sub(/.*\//,"")])  # Grab file name
  x[:path].sub!(/\/\w+$/,"")                       # remove file name from path
end
结果:
=>[“bin/ruby”、“usr/name/subdir”]


所需结果:
=>[{:path=>“bin/ruby”,:tag=>“v_10”,:file=>“file1”},{:path=>“usr/name/subdir”,:tag=>“v_12”,:file=>“file2”}]
您不想
收集
,您需要
每个
。Collect将输入哈希映射到每个块的输出,块的输出是
.sub
调用的结果,这意味着您将得到一个转换后的
:path
值的平面数组

您也可以直接设置键
:file
,而不是构建新哈希并尝试合并它:

paths = [{:path=>"bin/ruby/file1", :tag=>"v_10"}, {:path=>"usr/name/subdir/file2", :tag=>"v_12"}]

paths.each do |x|
  x[:file] = x[:path].sub(/.*\//, '')
  x[:path].sub!(/\/\w+$/,"")                       # remove file name from path
end

puts paths.inspect # [{:path=>"bin/ruby", :tag=>"v_10", :file=>"file1"}, {:path=>"usr/name/subdir", :tag=>"v_12", :file=>"file2"}]

功能型版本

paths.map do |path| 
  parts = path[:path].split('/'); 
  { 
    :path => parts.first(parts.length - 1).join('/'), 
    :tag => path[:tag], 
    :file => parts.last
  }
end

收集
收集
collect
本来可以(使用
merge!
而不是
merge
)但是有点pointless@muistooshort任何一个选项都是错误的,他只返回了一个值,
x[:path].sub!(/\/\w+$/,“”)
来自blockmeagar,感谢您解释我的代码不起作用的原因+答案。我的印象是,我们无法使用
每个
就地修改(因此我尝试使用
收集
)。在这里创建
x[:文件]
是如何工作的?是因为数组项指向散列,而指针实际上没有改变(因此
每个
都有效)?您正在迭代对象数组,每次迭代都将
x
设置为数组中的下一个对象。在Ruby中,对象是通过值分配的,因此修改
x
将修改对象
x
指向。如果希望保留数组的原始版本不变,但需要返回全新的对象,或者两个数组都将包含对相同对象的引用,则执行
collect
没有错。块的返回值之所以相关,唯一原因是他使用的是
collect
,如果他使用了
collect
,那么块的返回值就不相关了。你的答案仍然有一个打字错误,因为你的第一句话没有意义。