Arrays 转换数组
我有一个方法返回一组日期之间的年和月Arrays 转换数组,arrays,ruby,hash,Arrays,Ruby,Hash,我有一个方法返回一组日期之间的年和月 d = (from..to).map {|d| [ d.year, d.month ] }.uniq 我可以像这样迭代每个元素: d.each do |elm| #For Year puts elm[0] #For Month Number puts elm[1] end 如何更改该方法,以便按如下方式进行迭代,以增强代码的可读性,并通常使其更容易 elm.month_number elm.year 使用类或结构。e、 g YearM
d = (from..to).map {|d| [ d.year, d.month ] }.uniq
我可以像这样迭代每个元素:
d.each do |elm|
#For Year
puts elm[0]
#For Month Number
puts elm[1]
end
如何更改该方法,以便按如下方式进行迭代,以增强代码的可读性,并通常使其更容易
elm.month_number
elm.year
使用类或结构。e、 g
YearMonth = Struct.new(:year, :month)
d = (from..to).map{|d| YearMonth.new(d.year, d.month)}.uniq
尽管如此,这并不是一种最佳的方法。考虑这一点:
d = (from.year .. to.year).flat_map { |year|
from_month = year == from.year ? from.month : 1
to_month = year == to.year ? to.month : 12
(from_month..to_month).map { |month| YearMonth.new(year, month) }
}
这避免了创建一个巨大的日期数组,以及另一个由
映射产生的数组,该数组可以连续运行数月(即使没有那么紧凑)。使用类或结构。e、 g
YearMonth = Struct.new(:year, :month)
d = (from..to).map{|d| YearMonth.new(d.year, d.month)}.uniq
尽管如此,这并不是一种最佳的方法。考虑这一点:
d = (from.year .. to.year).flat_map { |year|
from_month = year == from.year ? from.month : 1
to_month = year == to.year ? to.month : 12
(from_month..to_month).map { |month| YearMonth.new(year, month) }
}
这避免了创建一个巨大的日期数组,以及另一个由映射产生的数组,并且可以连续运行数月(即使它没有那么紧凑)。我认为您正在寻找如下所述的数组自动解包:
我认为您正在寻找如下所述的阵列自动解包:
您也可以这样做(创建一个具有year
和month
属性的CustomDate
类):
您也可以这样做(创建一个具有year
和month
属性的CustomDate
类):
你所做的是多余的。保持日期元素不变(我假设它们是date
对象)
你所做的是多余的。保持日期元素不变(我假设它们是date
对象)
在其他答案中有一些很好的讨论,但是在没有必要的情况下,在每年的365天中迭代仅仅得到12个date对象似乎很愚蠢
不要从从
迭代到到
,而是从每个月开始计算整数个月,然后在该范围内迭代。看一看:
from = Date.civil(2013, 7, 1)
to = Date.civil(2015, 11, 23)
from_mos = 12 * from.year + from.month - 1
to_mos = 12 * to.year + to.month - 1
dates = (from_mos..to_mos).map do |mos|
year, month = mos.divmod(12)
Date.civil(year, month + 1, 1)
end
现在,日期
是一个可枚举的日期,产生每个月的第一天的日期,即2013-07-01、2013-08-01、…2015-11-01,您可以如下使用
dates.each do |date|
puts "Year #{date.year}, month #{date.month}"
end
# => Year 2013, month 7
# Year 2013, month 8
# ...
# Year 2015, month 10
# Year 2015, month 11
另外,如果您想麻烦地定义一个类或结构,我建议您直接使用范围API:
YearMonth = Struct.new(:year, :month) do
def succ
next_year, next_month = months.succ.divmod(12)
self.class.new(next_year, next_month + 1)
end
def <=>(other)
months <=> other.months
end
protected
def months
12 * year + month - 1
end
end
在其他答案中有一些很好的讨论,但是在没有必要的情况下,在每年的365天中迭代仅仅得到12个date对象似乎很愚蠢
不要从从
迭代到到
,而是从每个月开始计算整数个月,然后在该范围内迭代。看一看:
from = Date.civil(2013, 7, 1)
to = Date.civil(2015, 11, 23)
from_mos = 12 * from.year + from.month - 1
to_mos = 12 * to.year + to.month - 1
dates = (from_mos..to_mos).map do |mos|
year, month = mos.divmod(12)
Date.civil(year, month + 1, 1)
end
现在,日期
是一个可枚举的日期,产生每个月的第一天的日期,即2013-07-01、2013-08-01、…2015-11-01,您可以如下使用
dates.each do |date|
puts "Year #{date.year}, month #{date.month}"
end
# => Year 2013, month 7
# Year 2013, month 8
# ...
# Year 2015, month 10
# Year 2015, month 11
另外,如果您想麻烦地定义一个类或结构,我建议您直接使用范围API:
YearMonth = Struct.new(:year, :month) do
def succ
next_year, next_month = months.succ.divmod(12)
self.class.new(next_year, next_month + 1)
end
def <=>(other)
months <=> other.months
end
protected
def months
12 * year + month - 1
end
end
这不是OP要求的,而是推荐的方式。您的意思是OP要求elm.month
,而这种方式只使用month
?如果是这样的话,我会说你在技术上是对的,但这真的是一个显著的区别吗?是否有任何理由选择elm.month
而不是month
?这正是我所需要的,谢谢!也许我对这个问题不是很清楚。道歉that@sawa在我之后回答,我实际上认为他的解决方案明显更好,因为它更干净,更不迂回。这不是OP要求的,而是推荐的方式。你的意思是OP要求elm.month
,而这种方式只使用month
?如果是这样的话,我会说你在技术上是对的,但这真的是一个显著的区别吗?是否有任何理由选择elm.month
而不是month
?这正是我所需要的,谢谢!也许我对这个问题不是很清楚。道歉that@sawa在我之后回答,我实际上认为他的解决方案明显更好,因为它更干净,更不迂回。这不是每天都会出现,不是每个月都会出现吗?我正试图让它发挥作用,因为我同意你的观点,它似乎没有我的解决方案那么迂回。但是我无法让它工作:使用from
和to
作为日期对象,我得到了范围的未定义方法uniq。通过一些谷歌搜索,看起来Range#map
(就像使用的OP)是唯一的方法<代码>范围#到_a
返回一个空集。我错过了什么吗?对不起,我错过了到a
(Date.new(2015,11,1)…Date.new(2015,5,1))。到a
返回[]
…?哈哈,别介意,我,那应该是从2015,5,1
到2015,11,1
这不是每天都会返回吗,不是每个月都这样吗?我正努力让它发挥作用,因为我同意你的观点,它似乎没有我的解决方案那么迂回。但是我无法让它工作:使用from
和to
作为日期对象,我得到了范围的未定义方法uniq。通过一些谷歌搜索,看起来Range#map
(就像使用的OP)是唯一的方法<代码>范围#到_a
返回一个空集。我遗漏了什么吗?对不起,我遗漏了到a
(Date.new(2015,11,1)…Date.new(2015,5,1))。到a
返回[]
…?哈哈,别介意,我,那应该是从2015,5,1
到2015,11,1