按属性对数组中的连续哈希进行分组

时间:2014-08-29 07:27:59

标签: ruby

我希望能够从一系列约会中找到n x个连续约会的组。

我的数据如下:

  [{:event_id=>295, :appointment=>false, :accounted=>false},
   {:event_id=>296, :appointment=>false, :accounted=>false},
   {:event_id=>297, :appointment=>false, :accounted=>false},
   {:event_id=>311, :appointment=>false, :accounted=>false},
   {:event_id=>312, :appointment=>false, :accounted=>false},
   {:event_id=>313, :appointment=>false, :accounted=>false},
   {:event_id=>314, :appointment=>396, :accounted=>false},
   {:event_id=>315, :appointment=>397, :accounted=>false},
   {:event_id=>316, :appointment=>398, :accounted=>false},
   {:event_id=>317, :appointment=>false, :accounted=>false},
   {:event_id=>318, :appointment=>399, :accounted=>false},
   {:event_id=>319, :appointment=>false, :accounted=>false},
   {:event_id=>320, :appointment=>400, :accounted=>false},
   {:event_id=>321, :appointment=>401, :accounted=>false}]>

我希望能够找到任何3连续的预约组。因此,在这种情况下,事件314,315,316是唯一应该返回的组。

说实话,我甚至不确定从哪里开始...

3 个答案:

答案 0 :(得分:2)

您可以使用slice_before按连续约会对数组进行分组:

arr = [{:event_id=>295, :appointment=>false, :accounted=>false}, {:event_id=>296, :appointment=>false, :accounted=>false}, {:event_id=>297, :appointment=>false, :accounted=>false}, {:event_id=>311, :appointment=>false, :accounted=>false}, {:event_id=>312, :appointment=>false, :accounted=>false}, {:event_id=>313, :appointment=>false, :accounted=>false}, {:event_id=>314, :appointment=>396, :accounted=>false}, {:event_id=>315, :appointment=>397, :accounted=>false}, {:event_id=>316, :appointment=>398, :accounted=>false}, {:event_id=>317, :appointment=>false, :accounted=>false}, {:event_id=>318, :appointment=>399, :accounted=>false}, {:event_id=>319, :appointment=>false, :accounted=>false}, {:event_id=>320, :appointment=>400, :accounted=>false}, {:event_id=>321, :appointment=>401, :accounted=>false}]

groups = arr.slice_before(appointment: false) { |elt, state|
  a, b = state[:appointment], elt[:appointment] # get previous (a) and current (b) appointment
  state[:appointment] = elt[:appointment]       # update state
  a == false || b == false || a.succ != b       # slicing condition
}

groups.to_a
#=> [[{:event_id=>295, :appointment=>false, :accounted=>false}],
#    [{:event_id=>296, :appointment=>false, :accounted=>false}],
#    [{:event_id=>297, :appointment=>false, :accounted=>false}],
#    [{:event_id=>311, :appointment=>false, :accounted=>false}],
#    [{:event_id=>312, :appointment=>false, :accounted=>false}],
#    [{:event_id=>313, :appointment=>false, :accounted=>false}],
#    [{:event_id=>314, :appointment=>396, :accounted=>false},
#     {:event_id=>315, :appointment=>397, :accounted=>false},
#     {:event_id=>316, :appointment=>398, :accounted=>false}],
#    [{:event_id=>317, :appointment=>false, :accounted=>false}],
#    [{:event_id=>318, :appointment=>399, :accounted=>false}],
#    [{:event_id=>319, :appointment=>false, :accounted=>false}],
#    [{:event_id=>320, :appointment=>400, :accounted=>false},
#     {:event_id=>321, :appointment=>401, :accounted=>false}]]

解释切片条件

在以下情况下,元素将移动到新的组/数组中:

  • 以前的约会是假的(a == false
  • 当前约会为假(b == false
  • 以前的约会不是当前约会的继任者(a.succ != b

否则,即两个约会都不是false(我假设约会是false或整数)而前一个约会当前约会的继承者,他们保存在同一个数组中。

查找包含3个或更多项目的群组现在很简单:

groups.select { |g| g.size >= 3 }

#=> [[{:event_id=>314, :appointment=>396, :accounted=>false},
#     {:event_id=>315, :appointment=>397, :accounted=>false},
#     {:event_id=>316, :appointment=>398, :accounted=>false}]]

答案 1 :(得分:1)

您可以尝试这样:

arr, arr1 = [], []
my_data.each do |e|
    arr << e if e[:appointment] != false
    arr = [] if e[:appointment] == false
    if arr.count == 3
       arr1 += arr
       arr = []
    end
end

2.1.2 :084 > arr1
 => [{:event_id=>314, :appointment=>396, :accounted=>false}, {:event_id=>315, :appointment=>397, :accounted=>false}, {:event_id=>316, :appointment=>398, :accounted=>false}]

答案 2 :(得分:0)

这是我(农业)的看法。我也要尝试其他一些解决方案..

def remaining_event_apps_consecutive(n)             
        result = []
        consec =[]
        @eas.each do |ea|           
            if ea[:appointment] != false && ea[:accounted] ==false                          
                consec << ea                
            else                
                consec = [] 
            end
            if consec.size == n             
                result << consec
                consec = []
            end
        end
        result
    end