Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

sliceで先頭を除いた配列を返す(cdrっぽい事をする)

単にcdrっぽい事をしたい場合、
dropを使った方がシンプルになります。
コチラの記事を参照

配列系では、-1は末尾を示します。
sliceで-1を指定すると、末尾を返してくれます。
あらかじめサイズを知ってる必要がないので楽で良いですね。

> [1,2,3].slice(-1)
=> 3

これと範囲指定を組み合わせると、配列のサイズに関係なく、先頭を除いた配列を手にする事が出来ます。
「...」は例の如く境界を含まないので更に尻尾も排除してくれます。

> [1,2,3].slice(1..-1)
=> [2, 3]

> [1,2,3,4,5,6,7,8,9,10].slice(1..-1)
=> [2, 3, 4, 5, 6, 7, 8, 9, 10]

> [1,2,3,4,5,6,7,8,9,10].slice(1...-1)
=> [2, 3, 4, 5, 6, 7, 8, 9]

今回はcdrっぽい挙動をするメソッドが欲しかったので、こうしました。
cdrは非破壊メソッドです。

  • cdrモドキをしたい場合は「!」抜き
  • slice以降、先頭以外は絶対必要ない場合は「!」付き

という使い分けができます。

> a = [1,2,3,4]
=> [1, 2, 3, 4]

> a.slice(1,-1)
=> nil

> a.slice(1..-1)
=> [2, 3, 4]

> a
=> [1, 2, 3, 4]

> a.slice!(1..-1)
=> [2, 3, 4]

> a
=> [1]

おまけ

ちなみに、第二変数に負の数値を指定した場合、nilを返して来ます。

> [1,2,3,4,5,6,7,8,9,10].slice(1,-1)
=> nil

実際の方法

以上を応用すると、以前書いた各月の第一週の曜日と週番号を調べるRubyスクリプト

$ ruby -r 'date' -e 'puts (1..12).map {|i| %Q( %2s/1  Week #%2s %s) % [d = Date.new(2013,i,1), i, d.cweek, d.strftime("%A")].slice(1..-1) }'
  1/1  Week # 1 Tuesday
  2/1  Week # 5 Friday
  3/1  Week # 9 Friday
  4/1  Week #14 Monday
  5/1  Week #18 Wednesday
  6/1  Week #22 Saturday
  7/1  Week #27 Monday
  8/1  Week #31 Thursday
  9/1  Week #35 Sunday
 10/1  Week #40 Tuesday
 11/1  Week #44 Friday
 12/1  Week #48 Sunday

ワンライナー化できます。*1
変数d = Date.newのためにセミコロンを使わなくて良くなりました。
最後まで読まないと本当に代入する変数が分からないのがイマイチな気はしますが……

*1:細かいとこを少し変えましたが