【问题标题】:Check and select the latest one from the array of hashes检查并从哈希数组中选择最新的一个
【发布时间】:2015-07-08 07:13:14
【问题描述】:

我必须检查并从哈希数组中选择最新的一个。结构是这样的:

'histories':[
{
  {
   ...
  },
  'created': "date1",
  'items':[
    {
     'a': "Ready",
     'b': "dfknsknfs",
    },
    {
     'a': "sdfjbsf",
     'b': "hello23",
    }
  ]
},
{
  {
   ...
  },
  'created': "date2",
  'items':[
    {
     'a': "sknfkssd",
     'b': "ksdfjshs",
    },
    {
     'a': "Ready",
     'b': "shdfjsh",
    }
  ]
},
...
]

我必须首先找到值“Ready”,然后我必须选择最新的“created”日期。

我的尝试是这样的

ready_item = histories.select { |item| item.items.detect {|f| f.a == "Ready" } }
ready_item

但由于使用了detect,它只返回第一个检测到的值。但我需要得到最新的日期。它应该是什么可能的解决方案?

【问题讨论】:

  • 您的哈希语法错误,您的尝试也不起作用,因为表达式无效。
  • 我已经发布了一个类似的结构。无法从中发布数据。它的私人
  • 好的,但是item.items.detect 不行。
  • 我认为现在应该可以了。请检查
  • 没有。这是行不通的,因为在 ruby​​ 中访问哈希看起来像 item['items']['...'] 而不是在 javascript item.items... 中。

标签: ruby-on-rails ruby ruby-2.0 ruby-2.2


【解决方案1】:
histories.select { |h| 
  h[:items].detect {|f| f[:a] == 'Ready' } 
}.sort_by {|x| x[:created_at] }.last

【讨论】:

  • sort_by 被证明效率更高,但这里排序绝对是多余的,虽然对资源很贪婪。
  • 是的,reduce 在这里看起来更好。但它可以为许多项目搜索提前排序
  • 无论如何,最好考虑使用sort_by { |x| x[:created_at] } 而不是普通的sort。加上f.a 应该是f[:a]
  • 如果您主要关心的是编写 聪明 代码,那么排序可能看起来是多余的,但如果您专注于编写 clear 代码并避免过早优化,这很有道理。当您的排序需要方法分派时,首选sort_by。它使用 Schwartzian 变换进行了优化,使其更加高效。
  • 您的解决方案有效,但我在这里感到困惑。既然检测返回第一个可能的发现,那么sort_by 是如何处理它的呢?
【解决方案2】:

我已经使哈希或多或少有点红,如果我正确地取消了要求,那么你去:

hash = { histories:[
  { created: "2014-04-01",
    items:[
        { a: "Ready", b: "NOT to be chosen" },
        { a: "sdfjbsf", b: "hello23" }
  ]},  
  { created: "2015-04-01",
    items:[
        { a: "Ready", b: "to be chosen" },
        { a: "sdfjbsf", b: "hello23" }
  ]},  
  { created: "2014-03-01",
    items:[
        { a: "sknfkssd", b: "ksdfjshs" },  
        { a: "unready", b: "shdfjsh" }   
   ]}
]}

hash[:histories].select do |item|
  item[:items].detect do |item|
    item[:a] == 'Ready' # select ready only
  end 
end.reduce(nil) do |memo, item| # reduce to newest
  memo = item if memo.nil? || 
         Date.parse(memo[:created]) < Date.parse(item[:created])
end

#⇒ {
#  :created => "2015-04-01",
#    :items => [
#    [0] {
#      :a => "Ready",
#      :b => "to be chosen"
#    },
#    [1] {
#      :a => "sdfjbsf",
#      :b => "hello23"
#    }
#  ]
# }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 2013-07-20
    • 1970-01-01
    相关资源
    最近更新 更多