Ruby方式循环并相互检查后续值

时间:2010-12-11 15:56:55

标签: ruby-on-rails ruby

我有一个包含日期和值的数组。它的外观示例:

[
  {'1/1/2010' => 'aa'}, 
  {'1/1/2010' => 'bb'}, 
  {'1/2/2010' => 'cc'}, 
  {'1/2/2010' => 'dd'}, 
  {'1/3/2010' => 'ee'}
]

请注意,有些日期会重复。我试图以表格格式输出这个,我只想显示唯一的日期。所以我使用以下代码循环它以获得我想要的输出。

prev_date = nil
@reading_schedule.reading_plans.each do |plan|
  use_date = nil
  if plan.assigned_date != prev_date
    use_date = plan.assigned_date
  end
  prev_date = plan.assigned_date
  plan.assigned_date = use_date
end

结果表将看起来像这样

1/1/2010 aa
         bb
1/2/2010 cc
         dd
1/3/2010 ee

这项工作很好,但我是ruby的新手,并且想知道是否有更好的方法来做到这一点。

3 个答案:

答案 0 :(得分:2)

我不知道它好像好了,但您可以使用(例如)Enumerable#reduce按日期对值进行分组(需要Ruby> = 1.8.7;在此之前,您有Enumerable#inject )。

arr.reduce({}) { |memo, obj|
  obj.each_pair { |key, value|
    memo[key] = [] if ! memo.has_key?(key);
    memo[key] << value
  }
  memo
}.sort

=> [["1/1/2010", ["aa", "bb"]], ["1/2/2010", ["cc", "dd"]], ["1/3/2010", ["ee"]]]

你也可以使用Array#each来达到类似的效果。

答案 1 :(得分:2)

Enumerable.group_by是一个很好的起点:

require 'pp'

asdf = [
  {'1/1/2010' => 'aa'}, 
  {'1/1/2010' => 'bb'}, 
  {'1/2/2010' => 'cc'}, 
  {'1/2/2010' => 'dd'}, 
  {'1/3/2010' => 'ee'}
]

pp asdf.group_by { |n| n.keys.first }.map{ |a,b| { a => b.map { |c| c.to_a.last.last } } }
# >> [{"1/1/2010"=>["aa", "bb"]}, {"1/2/2010"=>["cc", "dd"]}, {"1/3/2010"=>["ee"]}]

哪个应该是您可以根据自己的意愿弯曲的数据结构。

答案 2 :(得分:1)

这完全是哈希的工作。

创建一个哈希,并使用date作为hashkey,将空数组作为hashvalue。

然后在hashvalue数组

中累积原始数组中的值