我想通过引入一个分割来分割以下数组,其中日期的差异是> 10天:
dates = [Date.parse('2017-06-26'), Date.parse('2017-07-04'), Date.parse('2017-11-30')]
#=> [Mon, 26 Jun 2017, Tue, 04 Jul 2017, Thu, 30 Nov 2017]
结果应如下:
[[Mon, 26 Jun 2017, Tue, 04 Jul 2017], [Thu, 30 Nov 2017]]
到目前为止,我有一个非常程序化的方法。它接受要分割的数组作为参数,不同组成员之间的最小差异,以及要评估以获得差异的属性。 (对于我的Date对象数组,我会留下最后一个参数,因为用于确定差异的值只是Date本身)
def split_by_attribute_diff array, split_size, attribute = :itself
groups = []
current_group = []
previous = current = nil
array.sort_by(&attribute).each do |e|
previous = current
current = e
if previous && current.send(attribute) - previous.send(attribute) > split_size
if current_group.count > 0
groups << current_group
current_group = []
end
end
current_group << current
end
if current_group.count > 0
groups << current_group
end
groups
end
我喜欢这种方法的方法是1)它的工作原理,2)算法复杂度只是sort_by的算法 - 在数组排序后,它只被遍历一次。 我想我唯一不喜欢的是它看起来应该更简单。是否有更多的Ruby-ish方法来完成我在这里所做的事情?
答案 0 :(得分:3)
如果你正确利用Ruby中的Enumerable库,尤其是chunk_while
,那么它并不是很难,这是专门用于根据逻辑测试将数组分成小块的:
require 'date'
dates = %w[
2017-06-26
2017-07-04
2017-11-21
2017-11-30
2017-12-30
].map { |d| Date.parse(d) }
r = dates.chunk_while do |a,b|
a + 10 > b
end
r.to_a.map { |a| a.map { |d| d.strftime('%Y-%m-%d') } }
# => [["2017-06-26", "2017-07-04"], ["2017-11-21", "2017-11-30"], ["2017-12-30"]]
答案 1 :(得分:1)
我的偏好是使用Enumerable#chunk_while(v2.3中的新增内容)或Enumerable#slice_when(v2.2中的新内容)来解决此问题和类似问题。但是,如果必须支持2.2之前的Ruby版本,则可以使用类似于以下的方法。
require 'date'
def group_em(dates)
fmt = '%Y-%m-%d'
dates.each_with_object([[]]) do |d,a|
if a.last.empty? || Date.strptime(d,fmt) <= Date.strptime(a.last.last,fmt) + 10
a.last << d
else
a << [d]
end
end
end
group_em %w| 2017-06-26 2017-07-04 2017-11-21 2017-11-30 2017-12-30 |
#=> [["2017-06-26", "2017-07-04"], ["2017-11-21", "2017-11-30"], ["2017-12-30"]]