🗓️
数字や日付が連続しているかを判定する方法
こんにちは!
ラブグラフエンジニアのひろです。
日付を一覧で表示する場所で、通常は 「2024年1月1日、2024年1月3日、2024年1月4日」 と羅列し、連続している日付だったら 「2024年1月1日~2024年1月3日」 のように省略して表示したいケースが出てきました。
パッと方法がわからなかったので書き残しておきます。
方法
each_cons(2).all? { |a, b| (b - a).to_i == 1 }
を使いました。
each_cons(2)で2つずつ値を取り出し、差分が1(つまり並んでいる)かどうかを検証していく方法です。
(順番がバラバラの配列では機能しないので、事前に sort して昇順に並び替える必要があります)
日付が連続しているかどうかの例
日付が連続しているかどうか.rb
# Range クラスにも使える
dates = (Date.new(2024,1,1)..Date.new(2024,1,3))
dates.each_cons(2).all? { |a, b| (b - a).to_i == 1 }
=> true # 連続している
dates = [Date.new(2024,1,1), Date.new(2024,1,3), Date.new(2024,1,4)]
dates.each_cons(2).all? { |a, b| (b - a).to_i == 1 }
=> false # 連続していない
# 月を跨いでも大丈夫
dates = [Date.new(2023,12,31), Date.new(2024,1,1), Date.new(2024,1,2)]
dates.each_cons(2).all? { |a, b| (b - a).to_i == 1 }
=> true
数字が連続しているかどうかの例
数字が連続しているかどうか.rb
numbers = [1,2,3,4,5,8,7,9,6]
numbers.each_cons(2).all? { |a, b| (b - a).to_i == 1 }
=> false # そのままだと連続していない
numbers.sort.each_cons(2).all? { |a, b| (b - a).to_i == 1 }
=> true # 並び替えると連続している
numbers = [1,2,4,5,6]
numbers.each_cons(2).all? { |a, b| (b - a).to_i == 1 }
=> false # 連続していない
終わりに
以上、バブルソートのようなイメージで比較して、配列の中身が連続しているかどうか判断する方法でした。
each_cons メソッドは知ってはいたものの、あまり使い所がなかったので、今回活かせる形が見つかってよかったです。
Discussion