【问题标题】:Ruby - rejecting hashes that are nested within arraysRuby - 拒绝嵌套在数组中的哈希
【发布时间】:2021-02-03 07:11:01
【问题描述】:

我试图拒绝数组中的特定哈希。由于事物的嵌套,我感到困惑

我有一个看起来像这样的哈希

hash = {
  "key1":
  [
    {
      "name": "foo",
      "id": 1
    },
    {
      "name": "foo",
      "id": 2
    },
    {
      "name": "bar",
      "id": 3
    }
  ],
  "key2":
  [
    {
      "name": "foo",
      "id": 1
    },
    {
      "name": "foo",
      "id": 2
    },
    {
      "name": "bar",
      "id": 3
    }
  ]
}

我需要遍历每个值并修改数组以拒绝任何具有 hash[:name] == "bar" 的哈希值,并且仍然保持其他所有内容不变。

我在努力

hash = hash.each_value do |value|
  value.reject {|v| v[:name] == "bar"}
end
=> {:key1=>[{:name=>"foo", :id=>1}, {:name=>"foo", :id=>2}, {:name=>"bar", :id=>3}],
 :key2=>[{:name=>"foo", :id=>1}, {:name=>"foo", :id=>2}, {:name=>"bar", :id=>3}]}

我可以用这样的方式删除它们:

hash.values.flatten.reject {|v| v[:name] == "bar"}
=> [{:name=>"foo", :id=>1}, {:name=>"foo", :id=>2}, {:name=>"foo", :id=>1}, {:name=>"foo", :id=>2}]

但我需要初始哈希保持不变

我希望得到这个:

hash = {
  "key1":
  [
    {
      "name": "foo",
      "id": 1
    },
    {
      "name": "foo",
      "id": 2
    }
  ],
  "key2":
  [
    {
      "name": "foo",
      "id": 1
    },
    {
      "name": "foo",
      "id": 2
    }
  ]
}

我也试过这条路线:

hash.reject do |key, value|
  value.each do |r|
    r[:name] == "bar"
  end
end

=> {}

非常感谢任何帮助 - 我很想解释我的逻辑哪里不好

我知道我对事物的迭代不正确,所有的嵌套让我有点困惑

【问题讨论】:

  • 我想我只需要从 hash.values 中删除额外的数组包装器并对其进行迭代

标签: ruby


【解决方案1】:

@Schwern 已经确定了您的代码存在的问题,所以我只会建议一个更像 Ruby 的解决方案。

hash = {
  "key1": [{ "name": "foo", "id": 1 },
           { "name": "foo", "id": 2 },
           { "name": "bar", "id": 3 }],
  "key2": [{ "name": "foo", "id": 1 },
           { "name": "foo", "id": 2 },
           { "name": "bar", "id": 3 }]
}
hash.transform_values { |arr| arr.reject { |h| h[:name] == "bar" } }
  #=> { "key1": [{ "name": "foo", "id": 1 },
  #              { "name": "foo", "id": 2 }],
  #     "key2": [{ "name": "foo", "id": 1 },
  #              { "name": "foo", "id": 2 }]
  #   }

Hash#transform_values。请注意,hash 没有发生突变。要修改hash,请使用Hash#transform_values!

【讨论】:

  • transform_values 非常方便。比较 transform_values { |v| v.reject }each_value { |v| v.reject! } 方法中哪一个效果最好会很有趣。
  • 我不知道它是否或多或少“类似红宝石”,但我更喜欢这种方法,因为我不清楚这两个陈述的意图,我认为这是矛盾的。 “修改数组”和“我需要初始哈希保持不变”
  • 谢谢 :) @engineersmnky 对不起,我没有很好地传达我的意图。意图基本上只是根据到期日期过滤掉一些哈希值。我正在转换这些数据,并想拒绝任何有过去日期的东西。我没有意识到我可以使用 transform_values,这就是我最终使用的
  • @tadman 在这之后我确实在其他几个地方使用了transform_values 方法,我只是不知道它的存在,需要学习更多方法
  • @magicfishy 无需道歉,但如果此答案解决了您的问题,请随时单击投票记录下的复选标记。
【解决方案2】:

您不是在修改散列,而是在散列中的值hash = hash.each_value 什么都不做,(each_value 的返回值没有记录)。

value.reject 确实拒绝了这些值,但没有到位。它返回一个新数组,并保留原始数组。

a = ["foo", "bar", "baz"]

# The modified array: ["foo", "baz"]
p a.reject { |v| v == "bar" }

# The original array is untouched: ["foo", "bar", "baz"]
p a

使用reject!就地修改每个数组。

hash.each_value do |value|
  value.reject! {|v| v[:name] == "bar"}
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    相关资源
    最近更新 更多