コレクション内のアイテムのグループ化
コレクション内のアイテムをグループ化するには、groupBy()関数を使用して、グループ化キーとして評価するクローズを提供します。
たとえば、単語のリストを指定すると、次のようにして各単語の長さに基づいて単語をグループ化できます:
def words = ['For', 'example', 'given', 'a', 'list', 'of', 'words', 'you', 'can',
'group', 'them', 'based', 'on', 'the', 'length', 'of', 'each', 'word']
def groupedByLength = words.groupBy{ it.length() }
これにより、
List
のMap
型の次の結果が生成されます:[
3:['For', 'you', 'can', 'the'],
7:['example'],
5:['given', 'words', 'group', 'based'],
1:['a'],
4:['list', 'them', 'each', 'word'],
2:['of', 'on', 'of'],
6:['length']
]
各グループのアイテム数の「カウント」を生成するには、
countBy()
関数を使用し、同じ種類のクロージャを渡してグループ化キーを決定します:def countsByLength = words.countBy{ it.length() }
これにより、単語lengthがマップ・キー、カウントが値であるマップが生成されます:
[3:4, 7:1, 5:4, 1:1, 4:4, 2:3, 6:1]
必要に応じて、コレクションをグループ化およびソートできます。 たとえば、前述の単語のリストをグループ化してカウントした後、単語に偶数の文字または奇数の文字が含まれているかどうかに基づいて、結果のマップをさらにグループにグループ化できます:
def evenOdd = countsByLength.groupBy{ it.key % 2 == 0 ? 'even' : 'odd' }
これにより、次のようなマップのマップが生成されます:
[odd:[3:4, 7:1, 5:4, 1:1],
even:[4:4, 2:3, 6:1]]
これらの関数は連鎖できるため、次の方法で、3文字未満の単語とその出現回数を含む単語のソートされたリストを生成できます:
def shortWordCounts = words.findAll{ it.length() < 3 }
.countBy{ it }
.sort{ it.key }
コードはコンパクトでわかりやすいですが、クローズ・パラメータの名前を変更して、さらに自己文書化できるようにする場合:
def shortWordCounts =
words.findAll{ word -> word.length() < 3 }
.countBy{ word -> word
.sort{ wordCountMapEntry -> wordCountMapEntry.key }
最終的な変動については、次のようなコメントを追加することもできます:
def shortWordCounts =
// Find words less than 3 characters
words.findAll{ word -> word.length() < 3 }
// Then count how many times each resulting word occurs
.countBy{ word -> word }
// Then sort alphabetically by word
.sort{ wordCountMapEntry -> wordCountMapEntry.key }
これにより、次の目的の結果が生成されます:
[a:1, of:2, on:1]