No Programming, No Life

プログラミング関連の話題や雑記

Groovyで頻出なコードの書き方のチートシート

※こちらの記事は Groovyのチートシート - No Programming, No Life へ転載致しました。

Groovyリファレンス系記事の一覧はこちら

はじめに

Groovyで頻出なコードの書き方のチートシート集。
動作確認はGroovy Version: 1.5.7 JVM: 1.6.0_10にて。

リスト (2009-01-27 更新)

assert [].size()      == 0
assert [1,2,3,4]       == (1..4)
assert [1,2,3] + [1]   == [1,2,3,1]
assert [1,2,3] + 1     == [1,2,3,1]
assert [1,2,3] << [1]  == [1,2,3,[1]]
assert [1,2,3,1] - [1] == [2,3]
assert [1,2,3] * 2     == [1,2,3,1,2,3]
assert [1,[2,3]].flatten() == [1,2,3]
assert [1,*[2,3]]          == [1,2,3] // リスト展開演算子
assert [1,2,3].reverse()   == [3,2,1]
assert [1,2,3].disjoint([4,5,6])
assert [1,2,3].intersect([4,3,1]) == [3,1]
assert [1,2,3].collect{ it + 3 }   == [4,5,6]
assert [1,2,3,1].unique().size()  == 3
assert [1,2,3,1].count(1) == 2
assert [1,2,3,4].min()    == 1
assert [1,2,3,4].max()    == 4
assert [1,2,3,4].sum()    == 10
assert [4,2,1,3].sort()   == [1,2,3,4]
assert [4,2,1,3].findAll{ it % 2 == 0 } == [4,2]
def animals = ['cat', 'kangaroo', 'koala', 'dog']
assert animals[2] == 'koala'
def kanimals = animals[1..2]
assert animals.findAll{ it =~ /k.*/ } == kanimals
assert animals.find{ it =~ /k.*/ }    == kanimals[0]
assert animals.grep(~/k.*/)          == kanimals
assert [[1, 2, 3, 4], ['a', 'b', 'c', 'd']].transpose() == [[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd']]
assert [[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd']].flatten() == [1, 'a', 2, 'b', 3, 'c', 4, 'd']

// 範囲の from と to を一緒に指定すると挿入になる
def list1 = ['a', 'b', 'c', 'd']
list1[1..1] = ['1', '2']
assert list1 == ['a', '1', '2', 'c', 'd']

// 範囲指定で一気に置き換え
def list3 = ['a', 'b', 'c', 'd', 'e']
list3[1..3] = ['1', '2', '3']
assert list3 == ['a', '1', '2', '3', 'e']

// インデックス指定だと、オブジェクトごと置き換え
def list2 = ['a', 'b', 'c']
list2[1] = ['1', '2']
assert list2 == ['a', ['1', '2'], 'c']

// 広い範囲を指定して置き換え
def list4 = ['a', 'b', 'c', 'd', 'e']
list4[1..3] = ['1', '2']
assert list4 == ['a', '1', '2', 'e']

マップ (2009-01-27 更新)

assert [:].size() == 0
def myMap = [a:1, b:2, c:3]
assert myMap instanceof HashMap
assert myMap.size()     == 3
assert myMap['a']        == 1
assert myMap.a           == 1
assert myMap.get('a')    == 1
assert myMap.get('a', 0) == 1 // デフォルト値を0として取得
assert myMap['d']        == null
assert myMap.d           == null
assert myMap.get('d')    == null
assert myMap.get('d', 0) == 0 // デフォルト値を0として取得
assert myMap.d           == 0 // デフォルト値がセットされた後なので0が取れる
myMap['e'] = 1
assert myMap.e == 1
myMap.e = 2
assert myMap.e == 2
def key = 'a'
assert ['x':1] == [x:1]
assert ['a':1] == [(key):1]
assert ['c':100, *:['a':11, 'aa':22, 'aaa':33]]
     == ['c':100, 'a':11, 'aa':22, 'aaa':33] // マップ展開演算子

範囲 (2008-12-25 更新)

assert 1..10 == new IntRange(1, 10)
assert 1..<5 == 1..4
assert -2..<2 == -2..1
assert 2..<-2 == 2..-1
assert (1..10).size() == 10
assert (1..5).step(1) == [1, 2, 3, 4, 5]
assert (1..5).step(2) == [1, 3, 5]
assert ('A'..'E').step(1) == ['A', 'B', 'C', 'D', 'E']
assert ('A'..'E').step(2) == ['A', 'C', 'E']
assert (3..1).isReverse()
assert !(1..3).isReverse()
assert (1..2).contains(1)
assert !(1..2).contains(3)
assert (1..5).containsAll([1, 2, 3, 4])

クロージャ

def add  = { x, y -> x + y }
def mult = { x, y -> x * y }
assert add(1, 3)  == 4
assert mult(1, 3) == 3
def min = { x, y -> [x,y].min() }
def max = { x, y -> [x,y].max() }
def atLeastTen = max.curry(10)
assert atLeastTen(5)  == 10
assert atLeastTen(15) == 15
def pairWise(list, Closure invoke) {
  if (list.size() < 2) return []
  def next = invoke(list[0], list[1])
  return [next] + pairWise(list[1..-1], invoke)
}
assert pairWise(1..5, add)  == [3,5,7,9]
assert pairWise(1..5, mult) == [2,6,12,20]
assert pairWise(1..5, min)  == [1,2,3,4]
assert pairWise(1..5, max)  == [2,3,4,5]
assert 'cbaxabc'   == ['a','b','c'].inject('x'){
           result, item -> item + result + item }
assert 'dcba-abcd' == ['a','b','c','d'].inject('-'){
           result, item -> item + result + item }
assert [1,2,3].grep{ it < 3 } == [1,2]
assert [1,2,3].any{ it % 2 == 0 }
assert [1,2,3].every{ it < 4 }
assert (1..9).collect{ it }.join()     == '123456789'
assert (1..4).collect{ it * 2 }.join() == '2468'

正規表現

def twister = 'she sells sea shells by the sea shore'
// 単語 'shore' を含む
assert twister =~ 'shore'
// 'sea' を2つ含む(2つの方法)
assert (twister =~ 'sea').count                 == 2
assert twister.split(/ /).grep(~/sea/).size() == 2
// 'sh' で始まる単語, \bは単語境界
def shwords = (twister =~ /sh[a-z]*\b/).collect{ it }.join(' ')
assert shwords == 'she shells shore'
// 3文字から成る4つの単語, \Sは空白文字以外の文字
assert (twister =~ /\b\S{3}\b/).count == 4
// 's' で始まり5あるいは6文字から成る3つの単語
assert (twister =~ /\bs\S{4}\S?\b/).count == 3
// 単語を 'X' で置き換え,\wは単語を構成する文字
assert twister.replaceAll(/\w+/, 'X') == 'X X X X X X X X'
// 'she' で始まり 'shore' で終わる
def pattern = ~/she.*shore/
assert pattern.matcher(twister).matches()
// 直前の単語が 'the' である 'sea' を 'ocean' に置換
def ocean = twister.replaceAll(/(?<=the )sea/, 'ocean')
assert ocean == 'she sells sea shells by the ocean shore'
// 1番目と2番目の単語のペアを入れ替え
def pairs = twister =~ /(\S+) (\S+) ?/
assert pairs.hasGroup()
twister = [1,0,2,3].collect{ pairs[it][0] }.join()
assert twister == 'sea shells she sells by the sea shore'

参考

Groovy JDK API Specification

Groovyイン・アクション

Groovyイン・アクション


List と Range の動き方が楽しい - 守破離
Groovyの奇妙な演算子(その2) - Grな日々(uehajの日記)

関連記事