【问题标题】:Elegantly return value(s) matching criteria from an array of nested hashes - in one line从嵌套哈希数组中优雅地返回匹配条件的值 - 在一行中
【发布时间】:2019-11-13 04:27:27
【问题描述】:

我这几天一直在寻找解决此问题的方法,希望有人能提供帮助。鉴于此数据结构:

'foo' => {
  'bar' => [
    {
      'baz' => {'faz' => '1.2.3'},
      'name' => 'name1'
    },
    {
      'baz' => {'faz' => '4.5.6'},
      'name' => 'name2'
    },
    {
      'baz' => {'faz' => '7.8.9'},
      'name' => 'name3'
    }
  ]
}

我需要找到以“4.”开头的“faz”的值,而不是使用每个。我必须使用“4”。 value 作为哈希的键,我将在循环“bar”时创建(如果我还不知道 '4.' 的值,显然我不能这样做),而且我不想循环两次。

理想情况下,会有一个优雅的单行解决方案将值“4.5.6”返回给我。

我找到了this article,但它并没有解决这个数据结构的全部复杂性,并且给出的唯一答案太冗长了;循环两次解决方案更具可读性。我在 Rails 4 上使用 Ruby 2.3,但无法升级。有没有 Ruby 大师可以指导我?

【问题讨论】:

  • foo 之前需要一个左大括号。我猜你也希望 foobar 成为文字(例如,’foo’’bar’)。当您使用它时,将哈希分配给一个变量(例如,h = { ‘foo’=>...}),以便读者可以在答案和 cmets 中引用该变量而无需定义它。
  • h['foo']['bar'].find { |hh| hh['baz']['faz'].start_with? '4.' }['baz']['faz']?呐!
  • 为什么是 Rails 标签?

标签: ruby ruby-on-rails-4 data-structures


【解决方案1】:

您可以使用select 来过滤结果。

data = {'foo' => {'bar' => [{'baz' => {'faz' => '1.2.3'}, 'name' => 'name1'}, {'baz' => {'faz' => '4.5.6'}, 'name' => 'name2'}, {'baz' => {'faz' => '7.8.9'}, 'name' => 'name3'}]}}

data.dig('foo', 'bar').select { |obj| obj.dig('baz', 'faz').slice(0) == '4' }
#=> [{"baz"=>{"faz"=>"4.5.6"}, "name"=>"name2"}]

# or if you prefer the square bracket style
data['foo']['bar'].select { |obj| obj['baz']['faz'][0] == '4' }

答案假定bar 数组中的每个元素都具有嵌套属性baz -> faz

如果您只期望一个结果,您可以改用find

【讨论】:

  • 你为什么用dig,而不是data['foo']['bar']obj['baz']['faz']? OP 并未以文字或示例的形式暗示嵌套键可能不存在。如果一个本应存在的密钥丢失了dig,将愉快地返回nil,掩盖遗漏。在这种情况下,我们希望引发异常。
  • @CarySwoveland 我更喜欢带有多个参数的dig,而不是链接[] 调用,仅用于样式。仍然需要存在,因为 selectslice 仅在返回正确的对象时才有效。但是,如果您更喜欢它的外观,可以将 data.dig('foo', 'bar') 替换为 data['foo']['bar']。用替代方法更新了答案。
  • 假设'baz' => {'faz' => '4.5.6'} 被错误地写成'bazz' => {'faz' => '4.5.6'} 然后使用dig(在查找4 时)将返回一个空数组,这可能是一个可能的结果。如果明确使用了'baz''faz',则会引发异常,这将很有帮助。当然还有其他遗漏的错误示例,使用 dig 会导致返回一个非空但错误的数组。
猜你喜欢
  • 2012-05-08
  • 1970-01-01
  • 2016-03-02
  • 2013-12-06
  • 2015-05-20
  • 1970-01-01
  • 1970-01-01
  • 2014-09-15
  • 1970-01-01
相关资源
最近更新 更多